From 4d077ffb3c8d094f6089ad89a6888e06d57bc3a0 Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Thu, 30 May 2024 12:07:35 -0400 Subject: [PATCH] Lock the journal insertion lock earlier in the process (#16025) --- warehouse/packaging/models.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/warehouse/packaging/models.py b/warehouse/packaging/models.py index c572bdd7b0fb..d664c09f112e 100644 --- a/warehouse/packaging/models.py +++ b/warehouse/packaging/models.py @@ -871,8 +871,8 @@ def __table_args__(cls): # noqa submitted_by: Mapped[User] = orm.relationship(lazy="raise_on_sql") -@db.listens_for(JournalEntry, "before_insert") -def ensure_monotonic_journals(config, mapper, connection, target): +@db.listens_for(db.Session, "before_flush") +def ensure_monotonic_journals(config, session, flush_context, instances): # We rely on `journals.id` to be a monotonically increasing integer, # however the way that SERIAL is implemented, it does not guarentee # that is the case. @@ -885,14 +885,17 @@ def ensure_monotonic_journals(config, mapper, connection, target): # The way this works, not even the SERIALIZABLE transaction types give # us this property. Instead we have to implement our own locking that # ensures that each new journal entry will be serialized. - connection.execute( - select( - func.pg_advisory_xact_lock( - cast(cast(target.__tablename__, REGCLASS), Integer), - _MONOTONIC_SEQUENCE, + for obj in session.new: + if isinstance(obj, JournalEntry): + session.execute( + select( + func.pg_advisory_xact_lock( + cast(cast(JournalEntry.__tablename__, REGCLASS), Integer), + _MONOTONIC_SEQUENCE, + ) + ) ) - ) - ) + return class ProhibitedProjectName(db.Model):