File Coverage

blib/lib/DBIx/TransactionManager/Extended.pm
Criterion Covered Total %
statement 86 86 100.0
branch 30 30 100.0
condition n/a
subroutine 17 17 100.0
pod 6 9 66.6
total 139 142 97.8


line stmt bran cond sub pod time code
1             package DBIx::TransactionManager::Extended;
2 7     7   228068 use 5.010001;
  7         52  
3 7     7   31 use strict;
  7         12  
  7         108  
4 7     7   27 use warnings;
  7         9  
  7         265  
5              
6             our $VERSION = "0.03";
7              
8 7     7   384 use parent qw/DBIx::TransactionManager/;
  7         237  
  7         35  
9              
10 7     7   18264 use Carp qw/croak/;
  7         14  
  7         252  
11 7     7   2376 use DBIx::TransactionManager::Extended::Txn;
  7         17  
  7         4032  
12              
13             sub context_data {
14 10     10 1 1164 my $self = shift;
15 10 100       22 croak 'CANNOT call context_data out of the transaction' unless $self->in_transaction;
16 9         58 return $self->{_context_data};
17             }
18              
19             # override
20 6     6 1 10310 sub txn_scope { DBIx::TransactionManager::Extended::Txn->new(@_) }
21              
22             # override
23             sub txn_begin {
24 60     60 0 26545 my ($self) = @_;
25 60 100       119 unless ($self->in_transaction) {
26             # create new context
27 44         256 $self->{_context_data} = {};
28 44         79 $self->{_hooks_before_commit} = [];
29 44         73 $self->{_hooks_after_commit} = [];
30             }
31 60         212 goto &DBIx::TransactionManager::txn_begin; ## XXX: hack to adjust the caller
32             }
33              
34             # override
35             sub txn_commit {
36 52     52 0 2254 my $self = shift;
37 52 100       62 return $self->SUPER::txn_commit() if @{ $self->active_transactions } != 1; # if it's a real commit
  52         98  
38              
39 36         135 my $context_data = $self->{_context_data};
40 36         43 my $hooks_before_commit = $self->{_hooks_before_commit};
41 36         64 my $hooks_after_commit = $self->{_hooks_after_commit};
42              
43 36 100       60 if (@$hooks_before_commit) {
44 15         21 eval { $_->($context_data) for @$hooks_before_commit };
  15         32  
45 15 100       2073 if ($@) {
46 1         3 $self->txn_rollback();
47 1         94 croak $@;
48             }
49 14         38 @$hooks_before_commit = ();
50             }
51              
52 35         44 my $ret = eval {
53 35         76 $self->SUPER::txn_commit();
54             };
55 35 100       1014 if ($@) {
56 2         20 $self->_reset_all();
57 2         169 croak $@;
58             }
59              
60 33 100       63 if (@$hooks_after_commit) {
61 22         28 eval { $_->($context_data) for @$hooks_after_commit };
  22         63  
62 22 100       1844 if ($@) {
63 1         4 $self->_reset_all();
64 1         80 croak $@;
65             }
66 21         55 @$hooks_after_commit = ();
67             }
68 32         43 %$context_data = ();
69              
70 32         65 return $ret;
71             }
72              
73             # override
74             sub txn_rollback {
75 9     9 0 1106 my $self = shift;
76 9         26 $self->_reset_all();
77 9         29 $self->SUPER::txn_rollback();
78             }
79              
80             sub _reset_all {
81 12         24 %{$_[0]->{_context_data}}
82 12         22 = @{$_[0]->{_hooks_before_commit}}
83 12     12   15 = @{$_[0]->{_hooks_after_commit}}
  12         33  
84             = ();
85             }
86              
87             sub add_hook_before_commit {
88 28     28 1 1469 my ($self, $hook) = @_;
89 28 100       51 croak 'CANNOT call add_hook_before_commit out of the transaction' unless $self->in_transaction;
90 27         128 push @{ $self->{_hooks_before_commit} } => $hook;
  27         45  
91 27         34 return $hook;
92             }
93              
94             sub add_hook_after_commit {
95 30     30 1 1816 my ($self, $hook) = @_;
96 30 100       49 croak 'CANNOT call add_hook_after_commit out of the transaction' unless $self->in_transaction;
97 29         143 push @{ $self->{_hooks_after_commit} } => $hook;
  29         47  
98 29         42 return $hook;
99             }
100              
101             sub remove_hook_before_commit {
102 3     3 1 664 my ($self, $hook) = @_;
103 3 100       18 croak 'CANNOT call remove_hook_before_commit out of the transaction' unless $self->in_transaction;
104 2         13 _remove_hook($self->{_hooks_before_commit}, $hook);
105             }
106              
107             sub remove_hook_after_commit {
108 3     3 1 607 my ($self, $hook) = @_;
109 3 100       8 croak 'CANNOT call remove_hook_after_commit out of the transaction' unless $self->in_transaction;
110 2         12 _remove_hook($self->{_hooks_after_commit}, $hook);
111             }
112              
113             sub _remove_hook {
114 4     4   6 my ($hooks, $hook) = @_;
115              
116 4         5 my $found;
117 4         6 for my $i (0..$#{$hooks}) {
  4         11  
118 8 100       17 if ($hook == $hooks->[$i]) {
119 2         3 $found = $i;
120 2         4 last;
121             }
122             }
123 4 100       9 splice @$hooks, $found, 1 if $found;
124 4 100       15 return $found ? $hook : undef;
125             }
126              
127             1;
128             __END__