from flask import request from flask_login import current_user, login_required from .. import create_app, db, socketio from ..models import User import json import jsonpatch import os ''' ' A list containing session ids of disconnected Socket.IO sessions. It is used ' to signal associated background tasks to stop. ''' disconnected = [] @socketio.on('connect') @login_required def connect(): # print('{} connected'.format(current_user.username)) # send('You entered the room {}'.format(request.sid), # room=request.sid) socketio.start_background_task(background_task, current_user.id, request.sid) @socketio.on('disconnect') @login_required def disconnect(): disconnected.append(request.sid) #print('{} disconnected'.format(current_user.username)) def background_task(user_id, session_id): ''' ' Sends initial corpus and job lists to the client. Afterwards it checks ' every 3 seconds if changes to the initial values appeared. If changes are ' detected, a RFC 6902 compliant JSON patch gets send. ' ' NOTE: The initial values are send as a init-* events. ' The JSON patches are send as update-* events. ''' app = create_app(os.getenv('FLASK_CONFIG') or 'default', main=False) with app.app_context(): user = db.session.query(User).filter_by(id=user_id).first() ''' Get current values from the database. ''' corpora = list(map(lambda x: x.to_dict(), user.corpora)) jobs = list(map(lambda x: x.to_dict(), user.jobs)) ''' Send initial values. ''' socketio.emit('init-corpora', json.dumps(corpora), room=session_id) socketio.emit('init-jobs', json.dumps(jobs), room=session_id) ''' TODO: Implement maximum runtime for this loop. ''' while session_id not in disconnected: # print(session_id + ' running') # socketio.emit('message', 'heartbeat', room=session_id) ''' Get current values from the database ''' new_corpora = list(map(lambda x: x.to_dict(), user.corpora)) new_jobs = list(map(lambda x: x.to_dict(), user.jobs)) ''' Compute JSON patches. ''' corpus_patch = jsonpatch.JsonPatch.from_diff(corpora, new_corpora) jobs_patch = jsonpatch.JsonPatch.from_diff(jobs, new_jobs) ''' In case there are patches, send them to the user. ''' if corpus_patch: socketio.emit('update-corpora', corpus_patch.to_string(), room=session_id) if jobs_patch: socketio.emit('update-jobs', jobs_patch.to_string(), room=session_id) ''' Set new values as a reference for the next iteration. ''' corpora = new_corpora jobs = new_jobs socketio.sleep(3) disconnected.remove(session_id) # print(session_id + ' stopped')