You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Failed in-transaction dispatch can be committed in SQLAlchemy backends #116
SQLAlchemyBackend and AsyncSQLAlchemyBackend flush event and outbox rows before dispatching in-transaction listeners.
If serialization/deserialization or a listener raises, append() fails as expected, but the pending rows remain in the SQLAlchemy session. A later, unrelated session.commit() persists an append that the caller observed as failed.
Reproduction
Configure a SQLAlchemy backend with an outbox and encryption.
Register an in-transaction listener for an event type.
Make listener dispatch fail, for example by making decryption raise.
Call append() and catch the exception.
Call session.commit().
Open a fresh session and load the stream.
Expected: the stream is empty; a failed append must not be persisted.
Actual: the stream contains the event. The outbox row can also be persisted.
This reproduces in both SQLAlchemyBackend and AsyncSQLAlchemyBackend.
Both implementations flush event/outbox rows before calling the dispatcher.
Proposed fix
Prepare and deserialize records for matching listeners before mutating the session, as the in-memory implementations already do:
Build RecordedRaw values.
Prepare dispatch, allowing failures to occur.
Create/update stream, insert events and outbox rows.
Invoke the already prepared listeners.
Alternatively, explicitly roll back or expunge all mutations before propagating a dispatch error. Preparing before mutation is preferable because it preserves the current atomicity model without taking ownership of the caller’s transaction.
Regression test
Add sync and async SQLAlchemy tests asserting that a dispatch/deserialization failure makes append() raise and that a subsequent session.commit() does not persist the event or outbox entry.
Activity