Repository navigation
fix: stop crashing and losing writes when a pool hook leaves a transaction open - #48
Merged
Merged
Conversation
…sing it A pool hook that runs a statement through the driver (a SQLAlchemy `checkout` listener, a psycopg-pool `check`) leaves the connection in a transaction. Bare reads then crashed on psycopg switching to autocommit, silently rolled the hook's settings back on asyncpg, a SQLAlchemy+asyncpg session tripped an assertion, a psycopg session's writes were rolled back, and isolation levels could not be set after the hook's SELECT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merged
jnsdls
added a commit
that referenced
this pull request
Oct 28, 2026
Bumps the version to 0.0.5 in `pyproject.toml`, `uv.lock` and `zero_server.__version__`. Nothing else changes. Since 0.0.4, `main` has gained one fix (#48): the SQLAlchemy and psycopg adapters no longer crash or lose writes when a pool hook hands a connection out with a transaction open. After merge, tag `v0.0.5` on main to publish to PyPI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- codesmith:footer --> --- <a href="https://app.blacksmith.sh/agent-labs-dev/codesmith/zero-python/pr/49?autoLogin=true&ref=codesmith_pr_footer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v3.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png" width="162" height="28"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1795821283&installation_model_id=434381&pr_number=49&ref=codesmith_pr_footer&repository=agent-labs-dev%2Fzero-python&return_to=https%3A%2F%2Fgithub.com%2Fagent-labs-dev%2Fzero-python%2Fpull%2F49&signature=c4ff320bb210d2e594509c31c900b17e7705df1a20fc139e77115568cf6bb5a8"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png" width="190" height="28"></picture></a> <sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need.</sup> <!-- codesmith:autofix:disabled --> <!-- /codesmith:footer --> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
A pool hook that runs a statement through the driver (a SQLAlchemy
checkoutlistener, a psycopg-poolcheck) hands the connection out INTRANS: in non-autocommit mode the driver opened a transaction for that statement. Found upgrading Nebula to 0.0.4 (agent-labs-dev/nebula#11193), whose_on_checkoutrunsSELECT 1; SET statement_timeout ….What broke on such a connection, by path:
ZQLDatabase.run, 0.0.4)SETs lostProgrammingError: can't change 'autocommit' nowProgrammingErrortransaction/ push sessionAssertionErrorin_send_begintransaction()is only a savepoint, pool rolls the writes back: mutation lostisolation_levelSET TRANSACTION ISOLATION LEVEL must be called before any query(after the hook'sSELECT 1)Fix: every adapter path that takes a connection first commits a transaction the pool left open, keeping what the hook set, then carries on unchanged. An IDLE connection costs a local status check, no round trip, so bare reads still go out with no
BEGIN/COMMIT.asyncpg direct: unaffected. asyncpg opens no implicit transactions, so a pool
setup/initleaves one open only by sendingBEGINitself.Evidence
New differential tests in
tests/wire/test_mutate.py. The hooked engine or pool runsSELECT 1thenSET statement_timeout = '4321ms'on every checkout:transactionwith no isolation, the 0.0.3 path)pytest795 passed,tests.compatcomplete, ruff and ty clean.Merge Danger
Door: two-way
Blast Radius: adapters
Only connections handed out INTRANS behave differently: the hook's transaction now commits up front. Before, it crashed, rolled back, or dropped writes. One
COMMITround trip per checkout in that case.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.