from datetime import datetime from .. import db, mail, socketio from ..email import create_message from ..models import Corpus, CorpusFile, Job, JobInput, JobResult, QueryResult ############################################################################### # SQLAlchemy event handlers # ############################################################################### @db.event.listens_for(Corpus, 'after_delete') @db.event.listens_for(CorpusFile, 'after_delete') @db.event.listens_for(Job, 'after_delete') @db.event.listens_for(JobInput, 'after_delete') @db.event.listens_for(JobResult, 'after_delete') @db.event.listens_for(QueryResult, 'after_delete') def ressource_after_delete(mapper, connection, ressource): event = 'user_{}_patch'.format(ressource.user_id) jsonpatch = [{'op': 'remove', 'path': ressource.jsonpatch_path}] room = 'user_{}'.format(ressource.user_id) socketio.emit(event, jsonpatch, room=room) @db.event.listens_for(Corpus, 'after_insert') @db.event.listens_for(CorpusFile, 'after_insert') @db.event.listens_for(Job, 'after_insert') @db.event.listens_for(JobInput, 'after_insert') @db.event.listens_for(JobResult, 'after_insert') @db.event.listens_for(QueryResult, 'after_insert') def ressource_after_insert_handler(mapper, connection, ressource): event = 'user_{}_patch'.format(ressource.user_id) jsonpatch = [ { 'op': 'add', 'path': ressource.jsonpatch_path, 'value': ressource.to_dict(include_relationships=False) } ] room = 'user_{}'.format(ressource.user_id) socketio.emit(event, jsonpatch, room=room) @db.event.listens_for(Corpus, 'after_update') @db.event.listens_for(CorpusFile, 'after_update') @db.event.listens_for(Job, 'after_update') @db.event.listens_for(JobInput, 'after_update') @db.event.listens_for(JobResult, 'after_update') @db.event.listens_for(QueryResult, 'after_update') def ressource_after_update_handler(mapper, connection, ressource): jsonpatch = [] for attr in db.inspect(ressource).attrs: # We don't want to handle changes in relationship fields # TODO: Find a way to handle this without a hardcoded list if attr.key in ['files', 'inputs', 'results']: continue history = attr.load_history() if not history.has_changes(): continue new_value = history.added[0] # In order to be JSON serializable, DateTime attributes must be # converted to a string if isinstance(new_value, datetime): new_value = new_value.isoformat() + 'Z' jsonpatch.append( { 'op': 'replace', 'path': '{}/{}'.format(ressource.jsonpatch_path, attr.key), 'value': new_value } ) # Job status update notification if it changed and wanted by the user if isinstance(ressource, Job) and attr.key == 'status': if ressource.creator.setting_job_status_mail_notifications == 'none': # noqa pass elif (ressource.creator.setting_job_status_mail_notifications == 'end' # noqa and ressource.status not in ['complete', 'failed']): pass else: msg = create_message( ressource.creator.email, 'Status update for your Job "{}"'.format(ressource.title), 'tasks/email/notification', job=ressource ) mail.send(msg) if jsonpatch: event = 'user_{}_patch'.format(ressource.user_id) room = 'user_{}'.format(ressource.user_id) socketio.emit(event, jsonpatch, room=room)