From 1507ba0d8e3234db304f4ef9254155c08908d2d0 Mon Sep 17 00:00:00 2001 From: Cyrille Bonnet Date: Thu, 23 Mar 2023 16:22:48 +0100 Subject: [PATCH 1/2] Added synchronization for registrations --- livesync/indico_livesync/base.py | 10 +- livesync/indico_livesync/handler.py | 7 +- livesync/indico_livesync/initial.py | 22 +++++ ...d11a6cab4_add_registrations_to_livesync.py | 95 +++++++++++++++++++ livesync/indico_livesync/models/queue.py | 22 +++++ livesync/indico_livesync/util.py | 5 + 6 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 livesync/indico_livesync/migrations/20230306_1520_86fd11a6cab4_add_registrations_to_livesync.py diff --git a/livesync/indico_livesync/base.py b/livesync/indico_livesync/base.py index ee0e366d0..d92621d46 100644 --- a/livesync/indico_livesync/base.py +++ b/livesync/indico_livesync/base.py @@ -15,13 +15,14 @@ from indico.modules.events.contributions.models.contributions import Contribution from indico.modules.events.contributions.models.subcontributions import SubContribution from indico.modules.events.models.events import Event +from indico.modules.events.registration.models.registrations import Registration from indico.modules.events.notes.models.notes import EventNote from indico.util.date_time import now_utc from indico.util.decorators import classproperty from indico_livesync.forms import AgentForm from indico_livesync.initial import (apply_acl_entry_strategy, query_attachments, query_contributions, query_events, - query_notes, query_subcontributions) + query_registrations, query_notes, query_subcontributions) from indico_livesync.models.queue import EntryType, LiveSyncQueueEntry from indico_livesync.plugin import LiveSyncPlugin @@ -143,6 +144,7 @@ def get_initial_query(self, model_cls, force): """ fn = { Event: query_events, + Registration: query_registrations, Contribution: query_contributions, SubContribution: query_subcontributions, Attachment: query_attachments, @@ -164,6 +166,7 @@ def get_data_query(self, model_cls, ids): """ fn = { Event: query_events, + Registration: query_registrations, Contribution: query_contributions, SubContribution: query_subcontributions, Attachment: query_attachments, @@ -184,6 +187,7 @@ def run_initial_export(self, batch_size, force=False, verbose=False): self._precache_categories() events = self.get_initial_query(Event, force) + registrations = self.get_initial_query(Registration, force) contributions = self.get_initial_query(Contribution, force) subcontributions = self.get_initial_query(SubContribution, force) attachments = self.get_initial_query(Attachment, force) @@ -193,6 +197,10 @@ def run_initial_export(self, batch_size, force=False, verbose=False): if not uploader.run_initial(events.yield_per(batch_size), events.count()): print('Initial export of events failed') return False + print('Exporting registrations') + if not uploader.run_initial(registrations.yield_per(batch_size), registrations.count()): + print('Initial export of registrations failed') + return False print('Exporting contributions') if not uploader.run_initial(contributions.yield_per(batch_size), contributions.count()): print('Initial export of contributions failed') diff --git a/livesync/indico_livesync/handler.py b/livesync/indico_livesync/handler.py index 3c71f1790..fe92f60aa 100644 --- a/livesync/indico_livesync/handler.py +++ b/livesync/indico_livesync/handler.py @@ -19,6 +19,7 @@ from indico.modules.events import Event from indico.modules.events.contributions.models.contributions import Contribution from indico.modules.events.contributions.models.subcontributions import SubContribution +from indico.modules.events.registration.models.registrations import Registration from indico.modules.events.notes.models.notes import EventNote from indico.modules.events.sessions import Session from indico.modules.events.sessions.models.blocks import SessionBlock @@ -39,14 +40,18 @@ def connect_signals(plugin): plugin.connect(signals.event.restored, _restored) plugin.connect(signals.event.contribution_created, _created) plugin.connect(signals.event.subcontribution_created, _created) + plugin.connect(signals.event.registration_created, _created) # deleted plugin.connect(signals.event.deleted, _deleted) plugin.connect(signals.event.contribution_deleted, _deleted) plugin.connect(signals.event.subcontribution_deleted, _deleted) + plugin.connect(signals.event.registration_deleted, _deleted) # updated plugin.connect(signals.event.updated, _updated) plugin.connect(signals.event.contribution_updated, _updated) plugin.connect(signals.event.subcontribution_updated, _updated) + plugin.connect(signals.event.registration_updated, _updated) + plugin.connect(signals.event.registration_form_edited, _updated) # event times plugin.connect(signals.event.times_changed, _event_times_changed, sender=Event) plugin.connect(signals.event.times_changed, _event_times_changed, sender=Contribution) @@ -113,7 +118,7 @@ def _moved(obj, old_parent, **kwargs): def _created(obj, **kwargs): - if not isinstance(obj, (Event, EventNote, Attachment, Contribution, SubContribution)): + if not isinstance(obj, (Event, EventNote, Attachment, Contribution, SubContribution, Registration)): raise TypeError(f'Unexpected object: {type(obj).__name__}') _register_change(obj, ChangeType.created) diff --git a/livesync/indico_livesync/initial.py b/livesync/indico_livesync/initial.py index cc0e687f2..923f0b5f5 100644 --- a/livesync/indico_livesync/initial.py +++ b/livesync/indico_livesync/initial.py @@ -13,6 +13,8 @@ from indico.modules.attachments.models.principals import AttachmentFolderPrincipal, AttachmentPrincipal from indico.modules.events import Event from indico.modules.events.contributions import Contribution +from indico.modules.events.registration.models.registrations import Registration +from indico.modules.users.models.users import User from indico.modules.events.contributions.models.principals import ContributionPrincipal from indico.modules.events.contributions.models.subcontributions import SubContribution from indico.modules.events.models.principals import EventPrincipal @@ -63,6 +65,26 @@ def query_events(ids=None): .order_by(Event.id) ) +def query_registrations(ids=None): + event_strategy = contains_eager(Registration.event) + apply_acl_entry_strategy(event_strategy.selectinload(Event.acl_entries), EventPrincipal) + + if ids is None: + export_filter = ~Registration.is_deleted & ~Event.is_deleted & _get_excluded_category_filter() + else: + export_filter = Registration.id.in_(ids) + + return ( + Registration.query + .join(Event) + .join(User) + .filter(export_filter) + .options( + event_strategy, + ) + .order_by(Registration.id) + ) + def query_contributions(ids=None): event_strategy = contains_eager(Contribution.event) diff --git a/livesync/indico_livesync/migrations/20230306_1520_86fd11a6cab4_add_registrations_to_livesync.py b/livesync/indico_livesync/migrations/20230306_1520_86fd11a6cab4_add_registrations_to_livesync.py new file mode 100644 index 000000000..0aea8eed6 --- /dev/null +++ b/livesync/indico_livesync/migrations/20230306_1520_86fd11a6cab4_add_registrations_to_livesync.py @@ -0,0 +1,95 @@ +"""add registrations to livesync + +Revision ID: 86fd11a6cab4 +Revises: ff1323696f67 +Create Date: 2023-03-06 15:20:02.568517 +""" + +import sqlalchemy as sa +from alembic import op + + + +# revision identifiers, used by Alembic. +revision = '86fd11a6cab4' +down_revision = 'ff1323696f67' +branch_labels = None +depends_on = None + + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute(''' + alter table plugin_livesync.queues add column registration_id integer; + create index ix_queues_registration_id on plugin_livesync.queues using btree (registration_id); + alter table plugin_livesync.queues add constraint ck_queues_valid_registration_entry check (type <> 8 OR attachment_id IS NULL AND category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND registration_id IS NOT NULL); + alter table plugin_livesync.queues add constraint fk_queues_registration_id_event_registrations foreign key (registration_id) references event_registration.registrations(id); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_enum_change; + alter table plugin_livesync.queues add constraint ck_queues_valid_enum_change CHECK (change = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9])); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_enum_type; + alter table plugin_livesync.queues add constraint ck_queues_valid_enum_type CHECK (type = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8])); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_attachment_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_attachment_entry CHECK (type <> 7 OR category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND registration_id IS NULL AND attachment_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_category_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_category_entry CHECK (type <> 1 OR attachment_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND registration_id IS NULL AND category_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_contribution_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_contribution_entry CHECK (type <> 3 OR attachment_id IS NULL AND category_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND registration_id IS NULL AND contribution_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_event_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_event_entry CHECK (type <> 2 OR attachment_id IS NULL AND category_id IS NULL AND contribution_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND registration_id IS NULL AND event_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_note_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_note_entry CHECK (type <> 6 OR attachment_id IS NULL AND category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND registration_id IS NULL AND note_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_session_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_session_entry CHECK (type <> 5 OR attachment_id IS NULL AND category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND subcontribution_id IS NULL AND registration_id IS NULL AND session_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_subcontribution_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_subcontribution_entry CHECK (type <> 4 OR attachment_id IS NULL AND category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND registration_id IS NULL AND subcontribution_id IS NOT NULL); + + ''') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute(''' + alter table plugin_livesync.queues drop column registration_id; + alter table plugin_livesync.queues drop constraint ck_queues_valid_registration_entry; + + alter table plugin_livesync.queues drop constraint ck_queues_valid_enum_change; + alter table plugin_livesync.queues add constraint ck_queues_valid_enum_change CHECK (change = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9])); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_enum_type; + alter table plugin_livesync.queues add constraint ck_queues_valid_enum_type CHECK (type = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7])); + + + alter table plugin_livesync.queues drop constraint ck_queues_valid_attachment_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_attachment_entry CHECK (type <> 7 OR category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND attachment_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_category_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_category_entry CHECK (type <> 1 OR attachment_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND category_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_contribution_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_contribution_entry CHECK (type <> 3 OR attachment_id IS NULL AND category_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND contribution_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_event_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_event_entry CHECK (type <> 2 OR attachment_id IS NULL AND category_id IS NULL AND contribution_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND event_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_note_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_note_entry CHECK (type <> 6 OR attachment_id IS NULL AND category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND note_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_session_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_session_entry CHECK (type <> 5 OR attachment_id IS NULL AND category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND subcontribution_id IS NULL AND session_id IS NOT NULL); + + alter table plugin_livesync.queues drop constraint ck_queues_valid_subcontribution_entry; + alter table plugin_livesync.queues add constraint ck_queues_valid_subcontribution_entry CHECK (type <> 4 OR attachment_id IS NULL AND category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NOT NULL); + + ''') + # ### end Alembic commands ### diff --git a/livesync/indico_livesync/models/queue.py b/livesync/indico_livesync/models/queue.py index 70461c214..5f86f66e4 100644 --- a/livesync/indico_livesync/models/queue.py +++ b/livesync/indico_livesync/models/queue.py @@ -38,6 +38,7 @@ class EntryType(int, IndicoEnum): session = 5 note = 6 attachment = 7 + registration = 8 _column_for_types = { @@ -48,6 +49,7 @@ class EntryType(int, IndicoEnum): EntryType.session: 'session_id', EntryType.note: 'note_id', EntryType.attachment: 'attachment_id', + EntryType.registration: 'registration_id', } @@ -131,6 +133,14 @@ class LiveSyncQueueEntry(db.Model): nullable=True ) + #: ID of the changed registration + registration_id = db.Column( + db.Integer, + db.ForeignKey('event_registration.registrations.id'), + index=True, + nullable=True + ) + #: ID of the changed session session_id = db.Column( 'session_id', @@ -213,6 +223,16 @@ class LiveSyncQueueEntry(db.Model): ) ) + registration = db.relationship( + 'Registration', + lazy=True, + backref=db.backref( + 'livesync_queue_entries', + cascade='all, delete-orphan', + lazy='dynamic' + ) + ) + subcontribution = db.relationship( 'SubContribution', lazy=False, @@ -260,6 +280,8 @@ def object(self): return self.note elif self.type == EntryType.attachment: return self.attachment + elif self.type == EntryType.registration: + return self.registration def __repr__(self): return format_repr(self, 'id', 'agent_id', 'change', 'type', diff --git a/livesync/indico_livesync/util.py b/livesync/indico_livesync/util.py index d254b708d..018cd2f6a 100644 --- a/livesync/indico_livesync/util.py +++ b/livesync/indico_livesync/util.py @@ -15,6 +15,7 @@ from indico.modules.events import Event from indico.modules.events.contributions.models.contributions import Contribution from indico.modules.events.contributions.models.subcontributions import SubContribution +from indico.modules.events.registration.models.registrations import Registration from indico.modules.events.notes.models.notes import EventNote from indico.modules.events.sessions.models.sessions import Session from indico.util.caching import memoize_request @@ -38,6 +39,8 @@ def obj_ref(obj): ref = {'type': EntryType.note, 'note_id': obj.id} elif isinstance(obj, Attachment): ref = {'type': EntryType.attachment, 'attachment_id': obj.id} + elif isinstance(obj, Registration): + ref = {'type': EntryType.registration, 'registration_id': obj.id} else: raise ValueError(f'Unexpected object: {obj.__class__.__name__}') return ImmutableDict(ref) @@ -61,6 +64,8 @@ def obj_deref(ref): return EventNote.get_or_404(ref['note_id']) elif ref['type'] == EntryType.attachment: return Attachment.get_or_404(ref['attachment_id']) + elif ref['type'] == EntryType.registration: + return Attachment.get_or_404(ref['registration_id']) else: raise ValueError('Unexpected object type: {}'.format(ref['type'])) From 088986201bb851ca843949e0c4d01aea5d435a5a Mon Sep 17 00:00:00 2001 From: Cyrille Bonnet Date: Fri, 24 Mar 2023 07:46:08 +0100 Subject: [PATCH 2/2] Fix linting and import sorting --- livesync/indico_livesync/base.py | 4 ++-- livesync/indico_livesync/handler.py | 2 +- livesync/indico_livesync/initial.py | 5 +++-- ...230306_1520_86fd11a6cab4_add_registrations_to_livesync.py | 5 +---- livesync/indico_livesync/util.py | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/livesync/indico_livesync/base.py b/livesync/indico_livesync/base.py index d92621d46..e5d896fb2 100644 --- a/livesync/indico_livesync/base.py +++ b/livesync/indico_livesync/base.py @@ -15,14 +15,14 @@ from indico.modules.events.contributions.models.contributions import Contribution from indico.modules.events.contributions.models.subcontributions import SubContribution from indico.modules.events.models.events import Event -from indico.modules.events.registration.models.registrations import Registration from indico.modules.events.notes.models.notes import EventNote +from indico.modules.events.registration.models.registrations import Registration from indico.util.date_time import now_utc from indico.util.decorators import classproperty from indico_livesync.forms import AgentForm from indico_livesync.initial import (apply_acl_entry_strategy, query_attachments, query_contributions, query_events, - query_registrations, query_notes, query_subcontributions) + query_notes, query_registrations, query_subcontributions) from indico_livesync.models.queue import EntryType, LiveSyncQueueEntry from indico_livesync.plugin import LiveSyncPlugin diff --git a/livesync/indico_livesync/handler.py b/livesync/indico_livesync/handler.py index fe92f60aa..550892980 100644 --- a/livesync/indico_livesync/handler.py +++ b/livesync/indico_livesync/handler.py @@ -19,8 +19,8 @@ from indico.modules.events import Event from indico.modules.events.contributions.models.contributions import Contribution from indico.modules.events.contributions.models.subcontributions import SubContribution -from indico.modules.events.registration.models.registrations import Registration from indico.modules.events.notes.models.notes import EventNote +from indico.modules.events.registration.models.registrations import Registration from indico.modules.events.sessions import Session from indico.modules.events.sessions.models.blocks import SessionBlock from indico.modules.events.timetable.models.entries import TimetableEntryType diff --git a/livesync/indico_livesync/initial.py b/livesync/indico_livesync/initial.py index 923f0b5f5..c0ac6635d 100644 --- a/livesync/indico_livesync/initial.py +++ b/livesync/indico_livesync/initial.py @@ -13,15 +13,15 @@ from indico.modules.attachments.models.principals import AttachmentFolderPrincipal, AttachmentPrincipal from indico.modules.events import Event from indico.modules.events.contributions import Contribution -from indico.modules.events.registration.models.registrations import Registration -from indico.modules.users.models.users import User from indico.modules.events.contributions.models.principals import ContributionPrincipal from indico.modules.events.contributions.models.subcontributions import SubContribution from indico.modules.events.models.principals import EventPrincipal from indico.modules.events.notes.models.notes import EventNote, EventNoteRevision +from indico.modules.events.registration.models.registrations import Registration from indico.modules.events.sessions import Session from indico.modules.events.sessions.models.blocks import SessionBlock from indico.modules.events.sessions.models.principals import SessionPrincipal +from indico.modules.users.models.users import User from indico_livesync.util import get_excluded_categories @@ -65,6 +65,7 @@ def query_events(ids=None): .order_by(Event.id) ) + def query_registrations(ids=None): event_strategy = contains_eager(Registration.event) apply_acl_entry_strategy(event_strategy.selectinload(Event.acl_entries), EventPrincipal) diff --git a/livesync/indico_livesync/migrations/20230306_1520_86fd11a6cab4_add_registrations_to_livesync.py b/livesync/indico_livesync/migrations/20230306_1520_86fd11a6cab4_add_registrations_to_livesync.py index 0aea8eed6..1c4f3f96f 100644 --- a/livesync/indico_livesync/migrations/20230306_1520_86fd11a6cab4_add_registrations_to_livesync.py +++ b/livesync/indico_livesync/migrations/20230306_1520_86fd11a6cab4_add_registrations_to_livesync.py @@ -5,11 +5,9 @@ Create Date: 2023-03-06 15:20:02.568517 """ -import sqlalchemy as sa from alembic import op - # revision identifiers, used by Alembic. revision = '86fd11a6cab4' down_revision = 'ff1323696f67' @@ -17,7 +15,6 @@ depends_on = None - def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.execute(''' @@ -69,7 +66,7 @@ def downgrade(): alter table plugin_livesync.queues drop constraint ck_queues_valid_enum_type; alter table plugin_livesync.queues add constraint ck_queues_valid_enum_type CHECK (type = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7])); - + alter table plugin_livesync.queues drop constraint ck_queues_valid_attachment_entry; alter table plugin_livesync.queues add constraint ck_queues_valid_attachment_entry CHECK (type <> 7 OR category_id IS NULL AND contribution_id IS NULL AND event_id IS NULL AND note_id IS NULL AND session_id IS NULL AND subcontribution_id IS NULL AND attachment_id IS NOT NULL); diff --git a/livesync/indico_livesync/util.py b/livesync/indico_livesync/util.py index 018cd2f6a..f53625b23 100644 --- a/livesync/indico_livesync/util.py +++ b/livesync/indico_livesync/util.py @@ -15,8 +15,8 @@ from indico.modules.events import Event from indico.modules.events.contributions.models.contributions import Contribution from indico.modules.events.contributions.models.subcontributions import SubContribution -from indico.modules.events.registration.models.registrations import Registration from indico.modules.events.notes.models.notes import EventNote +from indico.modules.events.registration.models.registrations import Registration from indico.modules.events.sessions.models.sessions import Session from indico.util.caching import memoize_request from indico.util.date_time import now_utc