from . import db, socketio from .models import Job, JobInput, JobResult import logging ############################################################################### # SQLAlchemy event handlers # ############################################################################### ############################################################################### ## Job events # ############################################################################### @db.event.listens_for(Job, 'after_update') def after_job_update(mapper, connection, job): jsonpatch = [] for attr in db.inspect(job).attrs: # We don't want to emit changes about relationship fields if attr.key in ['inputs', 'results']: continue history = attr.load_history() if not history.has_changes(): continue new_value = history.added[0] # DateTime attributes must be converted to a timestamp if attr.key in ['creation_date', 'end_date']: new_value = None if new_value is None else new_value.timestamp() jsonpatch.append( { 'op': 'replace', 'path': '/jobs/{}/{}'.format(job.id, attr.key), 'value': new_value } ) if jsonpatch: event = 'user_{}_patch'.format(job.user_id) room = 'user_{}'.format(job.user_id) socketio.emit(event, jsonpatch, room=room) @db.event.listens_for(Job, 'after_insert') def after_job_insert(mapper, connection, job): event = 'user_{}_patch'.format(job.user_id) jsonpatch = [ { 'op': 'add', 'path': '/jobs/{}'.format(job.id), 'value': job.to_dict(include_relationships=False) } ] room = 'user_{}'.format(job.user_id) socketio.emit(event, jsonpatch, room=room) @db.event.listens_for(Job, 'after_delete') def after_job_delete(mapper, connection, job): event = 'user_{}_patch'.format(job.user_id) jsonpatch = [{'op': 'remove', 'path': '/jobs/{}'.format(job.id)}] room = 'user_{}'.format(job.user_id) socketio.emit(event, jsonpatch, room=room) ############################################################################### ## JobInput events # ############################################################################### @db.event.listens_for(JobInput, 'after_update') def after_job_input_update(mapper, connection, job_input): jsonpatch = [] for attr in db.inspect(job_input).attrs: history = attr.load_history() if not history.has_changes(): continue new_value = history.added[0] jsonpatch.append( { 'op': 'replace', 'path': '/jobs/{}/inputs/{}/{}'.format(job_input.job_id, job_input.id, attr.key), 'value': new_value } ) if jsonpatch: event = 'user_{}_patch'.format(job_input.job.user_id) room = 'user_{}'.format(job_input.job.user_id) socketio.emit(event, jsonpatch, room=room) @db.event.listens_for(JobInput, 'after_insert') def after_job_input_insert(mapper, connection, job_input): event = 'user_{}_patch'.format(job_input.job.user_id) jsonpatch = [ { 'op': 'add', 'path': '/jobs/{}/inputs/{}'.format(job_input.job_id, job_input.id), 'value': job_input.to_dict(include_relationships=False) } ] room = 'user_{}'.format(job_input.job.user_id) socketio.emit(event, jsonpatch, room=room) @db.event.listens_for(JobInput, 'after_delete') def after_job_input_delete(mapper, connection, job_input): event = 'user_{}_patch'.format(job_input.job.user_id) jsonpatch = [ { 'op': 'remove', 'path': '/jobs/{}/inputs/{}'.format(job_input.job_id, job_input.id) } ] room = 'user_{}'.format(job_input.job.user_id) socketio.emit(event, jsonpatch, room=room) ############################################################################### ## JobResult events # ############################################################################### @db.event.listens_for(JobResult, 'after_update') def after_job_result_update(mapper, connection, job_result): jsonpatch = [] for attr in db.inspect(job_result).attrs: history = attr.load_history() if not history.has_changes(): continue new_value = history.added[0] jsonpatch.append( { 'op': 'replace', 'path': '/jobs/{}/results/{}/{}'.format(job_result.job_id, job_result.id, attr.key), 'value': new_value } ) if jsonpatch: event = 'user_{}_patch'.format(job_result.job.user_id) room = 'user_{}'.format(job_result.job.user_id) socketio.emit(event, jsonpatch, room=room) @db.event.listens_for(JobResult, 'after_insert') def after_job_result_insert(mapper, connection, job_result): event = 'user_{}_patch'.format(job_result.job.user_id) jsonpatch = [ { 'op': 'add', 'path': '/jobs/{}/results/{}'.format(job_result.job_id, job_result.id), 'value': job_result.to_dict(include_relationships=False) } ] room = 'user_{}'.format(job_result.job.user_id) socketio.emit(event, jsonpatch, room=room) @db.event.listens_for(JobResult, 'after_delete') def after_job_result_delete(mapper, connection, job_result): event = 'user_{}_patch'.format(job_result.job.user_id) jsonpatch = [ { 'op': 'remove', 'path': '/jobs/{}/results/{}'.format(job_result.job_id, job_result.id) } ] room = 'user_{}'.format(job_result.job.user_id) socketio.emit(event, jsonpatch, room=room)