Implement JSON patches for corpus and job lists.

This commit is contained in:
Patrick Jentsch 2019-08-29 10:42:53 +02:00
parent 98de581132
commit 0d3f54d655
2 changed files with 43 additions and 37 deletions

View File

@ -4,20 +4,22 @@ from flask_socketio import send
from .. import create_app, db, socketio from .. import create_app, db, socketio
from ..models import User from ..models import User
import json import json
import jsonpatch
import os import os
stop = [] '''
' A list containing session ids of disconnected Socket.IO sessions. It is used
' to signal associated background tasks to stop.
'''
disconnected = []
@socketio.on('connect') @socketio.on('connect')
@login_required @login_required
def connect(): def connect():
print('{} connected'.format(current_user.username)) # print('{} connected'.format(current_user.username))
send('You entered the room {}'.format(request.sid), # send('You entered the room {}'.format(request.sid),
room=request.sid) # room=request.sid)
if request.sid in stop:
stop.remove(request.sid)
socketio.start_background_task(background_task, socketio.start_background_task(background_task,
current_user.id, current_user.id,
request.sid) request.sid)
@ -26,52 +28,55 @@ def connect():
@socketio.on('disconnect') @socketio.on('disconnect')
@login_required @login_required
def disconnect(): def disconnect():
stop.append(request.sid) disconnected.append(request.sid)
print('{} disconnected'.format(current_user.username)) #print('{} disconnected'.format(current_user.username))
def background_task(user_id, session_id): def background_task(user_id, session_id):
''' '''
' Check user jobs every 3 seconds and emit a json patch on change ' 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) app = create_app(os.getenv('FLASK_CONFIG') or 'default', main=False)
corpora = []
jobs = []
with app.app_context(): with app.app_context():
user = db.session.query(User).filter_by(id=user_id).first() user = db.session.query(User).filter_by(id=user_id).first()
for corpus in user.corpora: ''' Get current values from the database. '''
corpora.append(corpus.to_dict()) 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', socketio.emit('init-corpora',
{'data': json.dumps(corpora)}, {'data': json.dumps(corpora)},
room=session_id) room=session_id)
for job in user.jobs:
jobs.append(job.to_dict())
socketio.emit('init-jobs', socketio.emit('init-jobs',
{'data': json.dumps(jobs)}, {'data': json.dumps(jobs)},
room=session_id) room=session_id)
while True: ''' TODO: Implement maximum runtime for this loop. '''
if session_id in stop: while session_id not in disconnected:
break
print(session_id + ' running') print(session_id + ' running')
socketio.emit('message', 'heartbeat', room=session_id) # socketio.emit('message', 'heartbeat', room=session_id)
''' Get current values from the database '''
new_corpora = [] new_corpora = list(map(lambda x: x.to_dict(), user.corpora))
new_jobs = [] new_jobs = list(map(lambda x: x.to_dict(), user.jobs))
for corpus in user.corpora: ''' Compute JSON patches. '''
new_corpora.append(corpus.to_dict()) corpus_patch = jsonpatch.JsonPatch.from_diff(corpora, new_corpora)
for job in user.jobs: jobs_patch = jsonpatch.JsonPatch.from_diff(jobs, new_jobs)
new_jobs.append(job.to_dict()) ''' In case there are patches, send them to the user. '''
if corpus_patch:
# socketio.send('new_corpora: ' + json.dumps(new_corpora), room=session_id) socketio.emit('update-corpora',
# socketio.send('new_jobs: ' + json.dumps(new_jobs), room=session_id) corpus_patch.to_string(),
# TODO: calculate json patch: new_corpora <-> corpora room=session_id)
# TODO: calculate json patch: new_jobs <-> jobs if jobs_patch:
# socketio.emit('update-corpora', {data: corpora_patch}, room=session_id) socketio.emit('update-jobs',
# socketio.emit('update-jobs', {data: jobs_patch}, room=session_id) jobs_patch.to_string(),
room=session_id)
''' Set new values as a reference for the next iteration. '''
corpora = new_corpora corpora = new_corpora
jobs = new_jobs jobs = new_jobs
socketio.sleep(3) socketio.sleep(3)
# TODO: Implement maximum runtime for this thread. disconnected.remove(session_id)
print(session_id + ' stopped') # print(session_id + ' stopped')

View File

@ -9,5 +9,6 @@ Flask-SocketIO
Flask-SQLAlchemy Flask-SQLAlchemy
Flask-Table Flask-Table
Flask-WTF Flask-WTF
jsonpatch
python-dotenv python-dotenv
redis redis