Repository navigation
feat: accept an AsyncConnection wherever publishing takes a session - #244
Merged
Merged
Conversation
broker.publish, publish_batch, cancel_timer, fetch_unprocessed, OutboxPublisher.publish and OutboxResponse now take a SQLAlchemy Core AsyncConnection through the existing required session= keyword, so code without the ORM can publish on the connection its domain writes run on. NOTIFY dedup keys on the connection's own transaction, so savepoints and autobegin behave as they do on a session.
Benchmark gate✅ gate passed
Gated (fails the build): |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every publish-side entry point now accepts a SQLAlchemy Core
AsyncConnectionas well as anAsyncSession:broker.publish,publish_batch,cancel_timer,fetch_unprocessed,OutboxPublisher.publish,OutboxResponseandOutboxPublishCommand. Code that uses Core without the ORM can publish on the connection its domain writes run on:Design
session=keyword is widened rather than addingconnection=. A second keyword (the faststream-sqlbroker shape) would make both optional, so forgetting both becomes a runtime error instead of a type error unless every entry point gets@overloadpairs. It would also need an exactly-one check and a second field on the command and response. Widening keeps the parameter required, breaks no caller, and the docs explain that the name covers both types.connectionfalls back to its own transaction when omitted, which silently drops the outbox guarantee. This PR doesn't copy that.sync_connection.get_nested_transaction() or get_transaction()), the same way it already does for sessions. The async proxies are regenerated per call and only weakly held, so keying on them would defeat the memo under autobegin.RootTransactionandNestedTransactioncan be weakly referenced, so the memo keeps working and a rolled-back savepoint can't suppress a later NOTIFY.SessionOrConnectionand the shared type guard live in a new_session.py, so the accepted types are defined in one place.Known edges, not addressed
sessionandawait session.connection()in one transaction gives two memo keys, so one extrapg_notifycan go out. Postgres coalesces it at delivery, so it's harmless.AsyncConnectionthat was constructed but never started passes the type check and then fails inside SQLAlchemy, not with ourTypeError.engine.connect()andengine.begin()always return a started connection.Tests
Integration tests on a real connection cover commit, rollback, autobegin (rows land only on
commit(), one NOTIFY), savepoint rollback re-emitting NOTIFY,publish_batchsharing the dedup,cancel_timer,fetch_unprocessed,OutboxResponseandOutboxPublisher.publish. A fake-broker test publishes with a connection, and the rejection test now pins the new error message.just test: 754 passed. ruff and ty are clean, andmkdocs build --strictpasses.