From af916fbffb739c0d0231adb61756e5700cb454e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Thu, 11 Apr 2019 18:53:55 +0200 Subject: [PATCH] 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. --- src/db/begin_transaction.cr | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/db/begin_transaction.cr b/src/db/begin_transaction.cr index a858afa..5fbe2d1 100644 --- a/src/db/begin_transaction.cr +++ b/src/db/begin_transaction.cr @@ -2,22 +2,29 @@ module DB module BeginTransaction # Creates a transaction from the current context. # 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 # yields a transaction from the current context. # Query the database through `Transaction#connection` object. # 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` # can be called explicitly. def transaction tx = begin_transaction begin yield tx - rescue e + rescue DB::Rollback 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 tx.commit unless tx.closed? end