File Coverage

blib/lib/Sub/Retry/Extended.pm
Criterion Covered Total %
statement 56 58 96.5
branch 21 24 87.5
condition 17 19 89.4
subroutine 8 8 100.0
pod 1 1 100.0
total 103 110 93.6


line stmt bran cond sub pod time code
1             package Sub::Retry::Extended;
2 3     3   43838 use strict;
  3         7  
  3         94  
3 3     3   11 use warnings;
  3         5  
  3         74  
4 3     3   12 use Carp qw/croak/;
  3         6  
  3         177  
5 3     3   1642 use Time::HiRes qw/sleep gettimeofday tv_interval/;
  3         3641  
  3         11  
6 3     3   1651 use parent qw/Exporter/;
  3         731  
  3         12  
7              
8             our @EXPORT = qw/retryX/;
9              
10             our $VERSION = '0.05';
11              
12             sub retryX {
13 18     18 1 10108 my (%args) = @_;
14              
15 18 50       72 my $code = delete($args{code}) or croak 'require code';
16 18 50       56 if (ref $code ne 'CODE') {
17 0         0 croak "'code' is not code ref";
18             }
19 18   50     50 my $times = delete($args{times}) || 1;
20 18   100     101 my $delay = delete($args{delay}) || delete($args{wait}) || 0;
21 18         24 my $retry_if = delete($args{retry_if});
22 18 50 66     54 if ($retry_if && ref $retry_if ne 'CODE') {
23 0         0 croak "'retry_if' is not code ref";
24             }
25 18   100     116 my $timeout = {
      100        
26             each => delete($args{each_timeout}) || 0,
27             total => delete($args{total_timeout}) || 0,
28             };
29              
30             # Most of below codes have been copied from Sub::Retry
31 18         18 my $err;
32 18   100 61   77 $retry_if ||= sub { $err = $@ };
  61         171  
33 18         37 my $n = 0;
34 18         81 my $lap = { start => [gettimeofday] };
35 18         49 while ( $times-- > 0 ) {
36 83         75 $n++;
37 83         218 $lap->{each} = [gettimeofday];
38 83 100       257 if (wantarray) {
    100          
39 12         13 my @ret = eval { $code->($n) };
  12         21  
40 12 100       86 unless ($retry_if->(@ret)) {
41 3         22 return @ret;
42             }
43 9         10 _timeout($timeout, $lap);
44             }
45             elsif (not defined wantarray) {
46 21         23 eval { $code->($n) };
  21         36  
47 21 100       145 unless ($retry_if->()) {
48 2         8 return;
49             }
50 19         23 _timeout($timeout, $lap);
51             }
52             else {
53 50         56 my $ret = eval { $code->($n) };
  50         104  
54 50 100       1921737 unless ($retry_if->($ret)) {
55 4         24 return $ret;
56             }
57 46         131 _timeout($timeout, $lap);
58             }
59 71 100       6055251 sleep $delay if $times; # Do not sleep in last time
60 71         168 _timeout($timeout, $lap);
61             }
62 3 100       366 die $err if $err;
63             }
64              
65             sub _timeout {
66 145     145   172 my ($timeout, $lap) = @_;
67              
68 145 100 100     393 if ( $timeout->{each}
69             && tv_interval($lap->{each}) > $timeout->{each} ) {
70 3         167 die 'retry timeout: each time';
71             }
72              
73 142 100 100     439 if ( $timeout->{total}
74             && tv_interval($lap->{start}) > $timeout->{total} ) {
75 3         112 die 'retry timeout: total time';
76             }
77              
78 139         410 return;
79             }
80              
81             1;
82              
83             __END__