Protect DBIC as best we can from the failure mode in 7cb35852
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / BlockRunner.pm
index be29701..0f884da 100644 (file)
@@ -7,7 +7,7 @@ use strict;
 use DBIx::Class::Exception;
 use DBIx::Class::Carp;
 use Context::Preserve 'preserve_context';
-use DBIx::Class::_Util qw(is_exception qsub);
+use DBIx::Class::_Util qw( is_exception qsub dbic_internal_try );
 use Scalar::Util qw(weaken blessed reftype);
 use Try::Tiny;
 use Moo;
@@ -122,7 +122,7 @@ sub _run {
   my $run_err = '';
 
   return preserve_context {
-    try {
+    dbic_internal_try {
       if (defined $txn_init_depth) {
         $self->storage->txn_begin;
         $txn_begin_ok = 1;
@@ -136,9 +136,14 @@ sub _run {
     my @res = @_;
 
     my $storage = $self->storage;
-    my $cur_depth = $storage->transaction_depth;
 
-    if (defined $txn_init_depth and ! is_exception $run_err) {
+    if (
+      defined $txn_init_depth
+        and
+      ! is_exception $run_err
+        and
+      defined( my $cur_depth = $storage->transaction_depth )
+    ) {
       my $delta_txn = (1 + $txn_init_depth) - $cur_depth;
 
       if ($delta_txn) {
@@ -151,29 +156,23 @@ sub _run {
         ) unless $delta_txn == 1 and $cur_depth == 0;
       }
       else {
-        $run_err = eval { $storage->txn_commit; 1 } ? '' : $@;
+        dbic_internal_try {
+          $storage->txn_commit;
+          1;
+        }
+        catch {
+          $run_err = $_;
+        };
       }
     }
 
     # something above threw an error (could be the begin, the code or the commit)
     if ( is_exception $run_err ) {
 
-      # attempt a rollback if we did begin in the first place
-      if ($txn_begin_ok) {
-        # some DBDs go crazy if there is nothing to roll back on, perform a soft-check
-        my $rollback_exception = $storage->_seems_connected
-          ? (! eval { $storage->txn_rollback; 1 }) ? $@ : ''
-          : 'lost connection to storage'
-        ;
-
-        if ( $rollback_exception and (
-          ! defined blessed $rollback_exception
-            or
-          ! $rollback_exception->isa('DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION')
-        ) ) {
-          $run_err = "Transaction aborted: $run_err. Rollback failed: $rollback_exception";
-        }
-      }
+      # Attempt a rollback if we did begin in the first place
+      # Will append rollback error if possible
+      $storage->__delicate_rollback( \$run_err )
+        if $txn_begin_ok;
 
       push @{ $self->exception_stack }, $run_err;