This is how the txnguard should really work
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / TxnScopeGuard.pm
1 package DBIx::Class::Storage::TxnScopeGuard;
2
3 use strict;
4 use warnings;
5 use Carp::Clan qw/^DBIx::Class/;
6
7 sub new {
8   my ($class, $storage) = @_;
9
10   $storage->txn_begin;
11   bless [ 0, $storage ], ref $class || $class;
12 }
13
14 sub commit {
15   my $self = shift;
16
17   $self->[1]->txn_commit;
18   $self->[0] = 1;
19 }
20
21 sub DESTROY {
22   my ($dismiss, $storage) = @{$_[0]};
23
24   return if $dismiss;
25
26   my $exception = $@;
27
28   carp 'A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error - bad'
29     unless $exception;
30
31   my $rollback_exception;
32   {
33     local $@;
34     eval { $storage->txn_rollback };
35     $rollback_exception = $@;
36   }
37
38   if ($rollback_exception && $rollback_exception !~ /DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION/) {
39     if ($exception) {
40       $@ = "Transaction aborted: ${exception} "
41           ."Rollback failed: ${rollback_exception}";
42     }
43     else {
44       carp "Rollback failed: ${rollback_exception}";
45     }
46   }
47 }
48
49 1;
50
51 __END__
52
53 =head1 NAME
54
55 DBIx::Class::Storage::TxnScopeGuard - Scope-based transaction handling
56
57 =head1 SYNOPSIS
58
59  sub foo {
60    my ($self, $schema) = @_;
61
62    my $guard = $schema->txn_scope_guard;
63
64    # Multiple database operations here
65
66    $guard->commit;
67  }
68
69 =head1 DESCRIPTION
70
71 An object that behaves much like L<Scope::Guard>, but hardcoded to do the
72 right thing with transactions in DBIx::Class. 
73
74 =head1 METHODS
75
76 =head2 new
77
78 Creating an instance of this class will start a new transaction (by
79 implicitly calling L<DBIx::Class::Storage/txn_begin>. Expects a
80 L<DBIx::Class::Storage> object as its only argument.
81
82 =head2 commit
83
84 Commit the transaction, and stop guarding the scope. If this method is not
85 called and this object goes out of scope (i.e. an exception is thrown) then
86 the transaction is rolled back, via L<DBIx::Class::Storage/txn_rollback>
87
88 =cut
89
90 =head1 SEE ALSO
91
92 L<DBIx::Class::Schema/txn_scope_guard>.
93
94 =head1 AUTHOR
95
96 Ash Berlin, 2008.
97
98 Insipred by L<Scope::Guard> by chocolateboy.
99
100 This module is free software. It may be used, redistributed and/or modified
101 under the same terms as Perl itself.
102
103 =cut