Skip to content

fix(db): release read transactions — no more idle-in-transaction on Postgres - #8

Merged
jcfrei merged 2 commits into
masterfrom
fix/pg-idle-in-transaction
Jul 28, 2026
Merged

fix(db): release read transactions — no more idle-in-transaction on Postgres#8
jcfrei merged 2 commits into
masterfrom
fix/pg-idle-in-transaction

Conversation

@jcfrei

@jcfrei jcfrei commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Fixes the production migration-starvation bug: with autocommit=False every SELECT opened a transaction that nothing ended, so pooled request threads (and the chat websocket) idled inside transactions holding ACCESS SHARE locks. The lock-safe plugin migrations' ALTER TABLE then hit its lock timeout on every boot (observed on erp.lambda.dev: internal migrations 0005/0006/0008/0009 failing since 0.6.3), columns were never created, and _persist() silently dropped edits to those fields — saves returned 200 OK but nothing stuck.

Fix: _PgConn tracks pending writes and rolls back immediately after a read when no write is uncommitted and no explicit transaction (submit/cancel) is active. psycopg's client-side cursor already buffered the result set, so post-release fetching works. Write flows and atomicity unchanged; SQLite untouched.

Test: tests/test_txn_release.py (Postgres CI) — read releases, helpers release, interleaved reads don't roll back pending writes, explicit-transaction reads keep their snapshot, and the real failure mode: a quiet reader thread + ensure_column succeeds.

🤖 Generated with Claude Code

jcfrei and others added 2 commits July 28, 2026 23:55
…ostgres

With autocommit=False every SELECT opened a transaction that nothing ended,
so pooled request threads and the chat websocket idled inside transactions,
pinning ACCESS SHARE locks. Lock-safe plugin migrations (ALTER TABLE) then
timed out on every boot in production, columns were never added, and saves
silently dropped fields for the missing columns (200 OK, edits lost).

_PgConn now tracks pending writes and rolls back right after a read when no
write is uncommitted and no explicit transaction (submit/cancel) is active.
psycopg's client-side cursor has already buffered the rows, so fetching after
the release works. Write flows and their atomicity are byte-for-byte
unchanged. tests/test_txn_release.py covers the semantics plus the real
failure mode: a quiet reader thread + ensure_column now succeeds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…key/value

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jcfrei
jcfrei merged commit 70495cd into master Jul 28, 2026
1 check passed
@jcfrei
jcfrei deleted the fix/pg-idle-in-transaction branch July 28, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant