File Coverage

blib/lib/WWW/Mechanize/Plugin/Retry.pm
Criterion Covered Total %
statement 12 59 20.3
branch 0 8 0.0
condition 0 3 0.0
subroutine 4 16 25.0
pod 5 5 100.0
total 21 91 23.0


line stmt bran cond sub pod time code
1             package WWW::Mechanize::Plugin::Retry;
2              
3 1     1   22396 use warnings;
  1         2  
  1         45  
4 1     1   7 use strict;
  1         3  
  1         45  
5 1     1   6 use base qw(Class::Accessor::Fast);
  1         6  
  1         978  
6             __PACKAGE__->mk_accessors(qw(retry_failed _retry_check_sub
7             _method_to_retry
8             _delays _delay_index));
9              
10             our $VERSION = '0.04';
11              
12             sub init {
13 0     0 1   my($class, $pluggable) = @_;
14 1     1   4180 no strict 'refs';
  1         2  
  1         817  
15 0           local $_;
16             eval "*WWW::Mechanize::Pluggable::$_ = \\&$_"
17 0           for qw(retry retry_if _method_to_retry _retry_fib
18             _retry_check_sub _delays _delays_max _delay_index retry_failed);
19              
20 0     0     $pluggable->pre_hook('get', sub { prehook(@_) } );
  0            
21 0     0     $pluggable->pre_hook('submit_form', sub { prehook(@_) } );
  0            
22 0     0     $pluggable->post_hook('get', sub { posthook(@_) } );
  0            
23 0     0     $pluggable->post_hook('submit_form', sub { posthook(@_) } );
  0            
24             }
25              
26             sub retry_if {
27 0     0 1   my($self, $sub, $times) = @_;
28              
29 0 0         if (defined $sub) {
30 0           $self->_retry_check_sub($sub);
31 0           $self->_delays($times);
32 0           $self->_delay_index(0);
33 0           $self->retry_failed(0);
34             }
35             else {
36 0           $sub;
37             }
38             }
39              
40             sub retry {
41 0     0 1   my($self, $times) = @_;
42 0     0     $self->retry_if(sub {$self->success}, $times);
  0            
43             }
44              
45             sub prehook {
46 0     0 1   my($pluggable, $mech, @args) = @_;
47 0           $pluggable->_method_to_retry($pluggable->last_method);
48            
49             # Don't skip the actual method call.
50 0           0;
51             }
52              
53             sub posthook {
54 0     0 1   my($pluggable, $mech, @args) = @_;
55              
56             # just leave if we have no retry check, or the check passes.
57 0           my $sub = $pluggable->_retry_check_sub;
58 0 0 0       if (!defined($sub) or $sub->()) {
59             # Ensure that the delay works next time round, and
60             # note that we did not fail retry.
61 0           $pluggable->_delay_index(-1);
62 0           $pluggable->retry_failed(0);
63 0           return;
64             }
65              
66             # Retry needed (check failed). Are we out of delays?
67 0           my $delay_index = $pluggable->_delay_index;
68 0 0         if ($delay_index == $pluggable->_delays) {
69             # Ran out this time.
70 0           $pluggable->_delay_index(-1);
71 0           $pluggable->retry_failed(1);
72             }
73             else {
74 0           my $current_delay = _retry_fib($delay_index);
75 0           $pluggable->_delay_index($pluggable->_delay_index+1);
76 0           sleep $current_delay;
77 0           my $method = $pluggable->_method_to_retry();
78 0           eval "\$pluggable->$method->(\@args)";
79             }
80             }
81              
82             # initial values in Fibonacci sequence
83             my @fib_for = (1,1);
84              
85             # Extend and cache as needed
86             sub _retry_fib_for {
87 0     0     my($n) = @_;
88             # walk up cache from last known value, applying F(n) = F(n-1)+F(n-2)
89 0           for my $i (@fib_for..$n) {
90 0           $fib_for[$i] = $fib_for[$i-1]+$fib_for[$i-2];
91             }
92 0           return;
93             }
94              
95             # Fibonacci # N
96             sub _retry_fib {
97 0     0     my($n) = @_;
98 0 0         if (!defined $fib_for[$n]) {
99 0           _retry_fib_for($n);
100             }
101 0           return $fib_for[$n];
102             }
103              
104              
105             1; # End of WWW::Mechanize::Plugin::Retry
106             __END__