from app import db, mail, socketio from app.email import create_message from app.models import ( Corpus, CorpusFile, Job, JobInput, JobResult, JobStatus, UserSettingJobStatusMailNotificationLevel ) from datetime import datetime from enum import Enum ############################################################################### # 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') def ressource_after_delete(mapper, connection, ressource): jsonpatch = [{'op': 'remove', 'path': ressource.jsonpatch_path}] room = f'users.{ressource.user_hashid}' socketio.emit('users.patch', 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') def ressource_after_insert_handler(mapper, connection, ressource): value = ressource.to_dict(backrefs=False, relationships=False) for attr in mapper.relationships: value[attr.key] = {} jsonpatch = [ {'op': 'add', 'path': ressource.jsonpatch_path, 'value': value} ] room = f'users.{ressource.user_hashid}' socketio.emit('users.patch', 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') def ressource_after_update_handler(mapper, connection, ressource): jsonpatch = [] for attr in db.inspect(ressource).attrs: if attr.key in mapper.relationships: continue if not attr.load_history().has_changes(): continue if isinstance(attr.value, datetime): value = attr.value.isoformat() + 'Z' elif isinstance(attr.value, Enum): value = attr.value.name else: value = attr.value jsonpatch.append( { 'op': 'replace', 'path': f'{ressource.jsonpatch_path}/{attr.key}', 'value': value } ) if isinstance(ressource, Job) and attr.key == 'status': _job_status_email_handler(ressource) if jsonpatch: room = f'users.{ressource.user_hashid}' socketio.emit('users.patch', jsonpatch, room=room) def _job_status_email_handler(job): if job.user.setting_job_status_mail_notification_level == UserSettingJobStatusMailNotificationLevel.NONE: # noqa return if job.user.setting_job_status_mail_notification_level == UserSettingJobStatusMailNotificationLevel.END: # noqa if job.status not in [JobStatus.COMPLETED, JobStatus.FAILED]: return msg = create_message( job.user.email, f'Status update for your Job "{job.title}"', 'tasks/email/notification', job=job ) mail.send(msg)