Return ErrTxClosed from Rollback when the connection is already closed (#2557)#2568
Closed
luongs3 wants to merge 1 commit into
Closed
Return ErrTxClosed from Rollback when the connection is already closed (#2557)#2568luongs3 wants to merge 1 commit into
luongs3 wants to merge 1 commit into
Conversation
When a transaction query's context is canceled mid-flight, the underlying pgconn is torn down (i/o timeout) but the dbTx state is left open. The next Rollback then issued "rollback" on the dead connection and surfaced the raw "conn closed" error instead of pgx.ErrTxClosed. Tx.Rollback documents that it returns an error matching ErrTxClosed when the Tx is already closed; a closed underlying connection is exactly that case. Check conn.IsClosed() up front and return ErrTxClosed, mirroring how Commit already consults connection state. Fixes jackc#2557.
Owner
|
As discussed in the issue, if any change is to be made, this isn't the direction we will go. |
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.
Fixes #2557.
Problem
When a transaction query's context is canceled mid-flight, the low-level
pgconn.PgConnis torn down (i/o timeout), but the outerpgx.dbTxstate is left open (tx.closedstaysfalse). The nextRollbackthen issues"rollback"on the already-dead connection and surfaces the raw"conn closed"error instead ofpgx.ErrTxClosed.This contradicts
Rollback's documented contract:A closed underlying connection means the transaction is, for all practical purposes, already closed — so callers reasonably expect
ErrTxClosed(which they can assert on) rather than an opaque low-level error.Reproduction (from the issue)
Fix
In
Rollback, checktx.conn.IsClosed()up front. If the connection is already closed, mark the tx closed and returnErrTxClosed. This mirrors howCommitalready consults connection state (tx.conn.PgConn().TxStatus()), and leaves the normal rollback path — including the existing "rollback failed →die()" handling — untouched.Tests
Added
TestTransactionRollbackAfterCanceledQueryReturnsErrTxClosed, which reproduces the issue's exact scenario (cancel apg_sleepquery, then roll back) and assertserrors.Is(err, pgx.ErrTxClosed). It fails onmaster(conn closed) and passes with this change. The existing transaction test suite continues to pass.