split connect_info parser out into private _normalize_connect_info
[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   {
29     local $@;
30
31     carp 'A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error. Rolling back.'
32       unless $exception;
33
34     eval { $storage->txn_rollback };
35     my $rollback_exception = $@;
36
37     if ($rollback_exception && $rollback_exception !~ /DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION/) {
38       if ($exception) {
39         $exception = "Transaction aborted: ${exception} "
40           ."Rollback failed: ${rollback_exception}";
41       }
42       else {
43         carp (join ' ',
44           "********************* ROLLBACK FAILED!!! ********************",
45           "\nA rollback operation failed after the guard went out of scope.",
46           'This is potentially a disastrous situation, check your data for',
47           "consistency: $rollback_exception"
48         );
49       }
50     }
51   }
52
53   $@ = $exception;
54 }
55
56 1;
57
58 __END__
59
60 =head1 NAME
61
62 DBIx::Class::Storage::TxnScopeGuard - Scope-based transaction handling
63
64 =head1 SYNOPSIS
65
66  sub foo {
67    my ($self, $schema) = @_;
68
69    my $guard = $schema->txn_scope_guard;
70
71    # Multiple database operations here
72
73    $guard->commit;
74  }
75
76 =head1 DESCRIPTION
77
78 An object that behaves much like L<Scope::Guard>, but hardcoded to do the
79 right thing with transactions in DBIx::Class. 
80
81 =head1 METHODS
82
83 =head2 new
84
85 Creating an instance of this class will start a new transaction (by
86 implicitly calling L<DBIx::Class::Storage/txn_begin>. Expects a
87 L<DBIx::Class::Storage> object as its only argument.
88
89 =head2 commit
90
91 Commit the transaction, and stop guarding the scope. If this method is not
92 called and this object goes out of scope (i.e. an exception is thrown) then
93 the transaction is rolled back, via L<DBIx::Class::Storage/txn_rollback>
94
95 =cut
96
97 =head1 SEE ALSO
98
99 L<DBIx::Class::Schema/txn_scope_guard>.
100
101 =head1 AUTHOR
102
103 Ash Berlin, 2008.
104
105 Insipred by L<Scope::Guard> by chocolateboy.
106
107 This module is free software. It may be used, redistributed and/or modified
108 under the same terms as Perl itself.
109
110 =cut