File Coverage

blib/lib/DBIx/TransactionManager/Extended.pm
Criterion Covered Total %
statement 89 89 100.0
branch 30 30 100.0
condition n/a
subroutine 18 18 100.0
pod 7 9 77.7
total 144 146 98.6


line stmt bran cond sub pod time code
1             package DBIx::TransactionManager::Extended;
2 7     7   60765 use 5.008001;
  7         18  
3 7     7   25 use strict;
  7         8  
  7         110  
4 7     7   27 use warnings;
  7         6  
  7         286  
5              
6             our $VERSION = "0.02";
7              
8 7     7   442 use parent qw/DBIx::TransactionManager/;
  7         234  
  7         30  
9              
10 7     7   14619 use Carp qw/croak/;
  7         9  
  7         238  
11 7     7   2386 use DBIx::TransactionManager::Extended::Txn;
  7         9  
  7         3684  
12              
13             # override
14 17     17 1 18084 sub new { shift->SUPER::new(@_)->_initialize }
15              
16             sub _initialize {
17 18     18   128 my $self = shift;
18 18         35 $self->{_in_commit_after_hook} = 0;
19 18         21 $self->{_context_data} = {};
20 18         23 $self->{_hooks_before_commit} = [];
21 18         21 $self->{_hooks_after_commit} = [];
22 18         30 $self;
23             }
24              
25             sub context_data {
26 8     8 1 1416 my $self = shift;
27 8 100       20 croak 'CANNOT call context_data out of the transaction' unless $self->in_transaction;
28 7         41 return $self->{_context_data};
29             }
30              
31             # override
32 6     6 1 33 sub txn_scope { DBIx::TransactionManager::Extended::Txn->new(@_) }
33              
34             # override
35             sub txn_commit {
36 51     51 0 7083 my $self = shift;
37 51 100       38 return $self->SUPER::txn_commit() if @{ $self->active_transactions } != 1;
  51         83  
38              
39 35         112 my $context_data = $self->{_context_data};
40 35         25 my $hooks_before_commit = $self->{_hooks_before_commit};
41 35         32 my $hooks_after_commit = $self->{_hooks_after_commit};
42              
43 35 100       47 if (@$hooks_before_commit) {
44 15         24 eval { $_->($context_data) for @$hooks_before_commit };
  15         46  
45 15 100       1531 if ($@) {
46 1         2 $self->txn_rollback();
47 1         93 croak $@;
48             }
49 14         36 @$hooks_before_commit = ();
50             }
51              
52 34         40 my $ret = eval {
53 34         70 $self->SUPER::txn_commit();
54             };
55 34 100       685 if ($@) {
56 2         4 $self->_reset_all();
57 2         208 croak $@;
58             }
59              
60 32 100       47 if (@$hooks_after_commit) {
61 22         34 local $self->{_in_commit_after_hook} = $self->{_in_commit_after_hook} + 1;
62 22 100       44 if ($self->{_in_commit_after_hook} == 1) {
63 8         7 eval { $_->($context_data) for @$hooks_after_commit };
  8         17  
64 8 100       1387 if ($@) {
65 1         3 $self->_reset_all();
66 1         75 croak $@;
67             }
68 7         29 @$hooks_after_commit = ();
69             }
70             }
71 31         33 %$context_data = ();
72              
73 31         54 return $ret;
74             }
75              
76             # override
77             sub txn_rollback {
78 8     8 0 1607 my $self = shift;
79 8         17 $self->_reset_all();
80 8         30 $self->SUPER::txn_rollback();
81             }
82              
83             sub _reset_all {
84 11         20 %{$_[0]->{_context_data}}
85 11         16 = @{$_[0]->{_hooks_before_commit}}
86 11     11   14 = @{$_[0]->{_hooks_after_commit}}
  11         29  
87             = ();
88             }
89              
90             sub add_hook_before_commit {
91 28     28 1 1502 my ($self, $hook) = @_;
92 28 100       43 croak 'CANNOT call add_hook_before_commit out of the transaction' unless $self->in_transaction;
93 27         98 push @{ $self->{_hooks_before_commit} } => $hook;
  27         32  
94 27         26 return $hook;
95             }
96              
97             sub add_hook_after_commit {
98 28     28 1 1980 my ($self, $hook) = @_;
99 28 100       38 croak 'CANNOT call add_hook_after_commit out of the transaction' unless $self->in_transaction;
100 27         97 push @{ $self->{_hooks_after_commit} } => $hook;
  27         39  
101 27         23 return $hook;
102             }
103              
104             sub remove_hook_before_commit {
105 3     3 1 455 my ($self, $hook) = @_;
106 3 100       6 croak 'CANNOT call remove_hook_before_commit out of the transaction' unless $self->in_transaction;
107 2         11 _remove_hook($self->{_hooks_before_commit}, $hook);
108             }
109              
110             sub remove_hook_after_commit {
111 3     3 1 480 my ($self, $hook) = @_;
112 3 100       6 croak 'CANNOT call remove_hook_after_commit out of the transaction' unless $self->in_transaction;
113 2         10 _remove_hook($self->{_hooks_after_commit}, $hook);
114             }
115              
116             sub _remove_hook {
117 4     4   2 my ($hooks, $hook) = @_;
118              
119 4         3 my $found;
120 4         5 for my $i (0..$#{$hooks}) {
  4         9  
121 8 100       16 if ($hook == $hooks->[$i]) {
122 2         1 $found = $i;
123 2         2 last;
124             }
125             }
126 4 100       8 splice @$hooks, $found, 1 if $found;
127 4 100       14 return $found ? $hook : undef;
128             }
129              
130             1;
131             __END__