Transactions¶
transaction() is an async context manager that runs everything inside the block on one connection, committing on exit and rolling back on exception. It yields a Transaction handle for raw SQL that must run on the transaction's connection. It can route by using= or by an explicit/ambient session (ferro.engines.session(...)). See the Transactions guide for semantics and patterns.
transaction(using=None, *, session=None)
async
¶
Run database operations inside a transaction context.
Yields a :class:~ferro.raw.Transaction handle bound to this transaction's
connection. The handle exposes execute / fetch_all / fetch_one
for raw SQL on the same connection — useful for setting Postgres GUCs,
advisory locks, and any one-off statement that doesn't fit a Model.
Examples:
>>> async with transaction() as tx:
... user = await User.create(name="Taylor")
... await tx.execute(
... "select set_config('request.jwt.claims', $1, true)",
... claims_json,
... )
Existing callers that don't bind the yielded value continue to work; the handle is simply discarded::
>>> async with transaction():
... user = await User.create(name="Taylor")
... await user.save()
Source code in src/ferro/models.py
Transaction
¶
Handle for a live transaction.
Obtained via async with transaction() as tx. Methods delegate to the
top-level :func:execute / :func:fetch_all / :func:fetch_one with this
transaction's route (a :class:RouteHandle built by
models.transaction()) passed explicitly, so they don't depend on the
ContextVar state. This makes the connection-affinity invariant
structurally impossible to violate from inside the async with block.
The handle becomes invalid once the async with block exits — any
subsequent call raises :class:RuntimeError.