Fix BeginTransaction#transaction error in rollback (#101)

When the rescued exception was caused by a protocol error, the
connection is in a corrupted state and executing the rollback
command might fail due to a subsequent protocol error - which is
irrelevant because the source of the corruption is described by
the original exception which must not be overlayed by a secondary one.
This commit is contained in:
Johannes Müller 2019-04-11 18:53:55 +02:00 committed by Brian J. Cardiff
parent 11b16cf5bc
commit af916fbffb

View file

@ -2,22 +2,29 @@ module DB
module BeginTransaction module BeginTransaction
# Creates a transaction from the current context. # Creates a transaction from the current context.
# If is expected that either `Transaction#commit` or `Transaction#rollback` # If is expected that either `Transaction#commit` or `Transaction#rollback`
# are called explictly to release the context. # are called explicitly to release the context.
abstract def begin_transaction : Transaction abstract def begin_transaction : Transaction
# yields a transaction from the current context. # yields a transaction from the current context.
# Query the database through `Transaction#connection` object. # Query the database through `Transaction#connection` object.
# If an exception is thrown within the block a rollback is performed. # If an exception is thrown within the block a rollback is performed.
# The exception thrown is blubbled unless it is a `DB::Rollback`. # The exception thrown is bubbled unless it is a `DB::Rollback`.
# From the yielded object `Transaction#commit` or `Transaction#rollback` # From the yielded object `Transaction#commit` or `Transaction#rollback`
# can be called explicitly. # can be called explicitly.
def transaction def transaction
tx = begin_transaction tx = begin_transaction
begin begin
yield tx yield tx
rescue e rescue DB::Rollback
tx.rollback unless tx.closed? tx.rollback unless tx.closed?
raise e unless e.is_a?(DB::Rollback) rescue e
unless tx.closed?
# Ignore error in rollback.
# It would only be a secondary error to the original one, caused by
# corrupted connection state.
tx.rollback rescue nil
end
raise e
else else
tx.commit unless tx.closed? tx.commit unless tx.closed?
end end