use strict;
use warnings;
+use Carp ();
sub new {
my ($class, $storage) = @_;
sub DESTROY {
my ($dismiss, $storage) = @{$_[0]};
- $storage->txn_rollback unless $dismiss;
+ return if $dismiss;
+
+ my $exception = $@;
+ Carp::cluck("A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or an error - bad")
+ unless $exception;
+
+ my $rollback_exception;
+ {
+ local $@;
+ eval { $storage->txn_rollback };
+ $rollback_exception = $@;
+ }
+ if ($rollback_exception && $rollback_exception !~ /DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION/) {
+ $storage->throw_exception(
+ "Transaction aborted: ${exception} "
+ . "Rollback failed: ${rollback_exception}"
+ );
+ }
}
1;
=head1 NAME
-DBIx::Class::Storage::TxnScopeGuard
+DBIx::Class::Storage::TxnScopeGuard - Scope-based transaction handling
=head1 SYNOPSIS
=head2 new
-Creating an instance of this class will start a new transaction. Expects a
+Creating an instance of this class will start a new transaction (by
+implicitly calling L<DBIx::Class::Storage/txn_begin>. Expects a
L<DBIx::Class::Storage> object as its only argument.
=head2 commit
Commit the transaction, and stop guarding the scope. If this method is not
-called (i.e. an exception is thrown) and this object goes out of scope then
-the transaction is rolled back.
+called and this object goes out of scope (i.e. an exception is thrown) then
+the transaction is rolled back, via L<DBIx::Class::Storage/txn_rollback>
=cut