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   47820 use strict;
  3         8  
  3         94  
3 3     3   10 use warnings;
  3         6  
  3         71  
4 3     3   11 use Carp qw/croak/;
  3         8  
  3         176  
5 3     3   1552 use Time::HiRes qw/sleep gettimeofday tv_interval/;
  3         3779  
  3         11  
6 3     3   1713 use parent qw/Exporter/;
  3         724  
  3         12  
7              
8             our @EXPORT = qw/retryX/;
9              
10             our $VERSION = '0.03';
11              
12             sub retryX {
13 18     18 1 11592 my (%args) = @_;
14              
15 18 50       102 my $code = delete($args{code}) or croak 'require code';
16 18 50       53 if (ref $code ne 'CODE') {
17 0         0 croak "'code' is not code ref";
18             }
19 18   50     51 my $times = delete($args{times}) || 1;
20 18   100     94 my $delay = delete($args{delay}) || delete($args{wait}) || 0;
21 18         26 my $retry_if = delete($args{retry_if});
22 18 50 66     56 if ($retry_if && ref $retry_if ne 'CODE') {
23 0         0 croak "'retry_if' is not code ref";
24             }
25 18   100     252 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         16 my $err;
32 18   100 61   71 $retry_if ||= sub { $err = $@ };
  61         182  
33 18         20 my $n = 0;
34 18         81 my $lap = { start => [gettimeofday] };
35 18         46 while ( $times-- > 0 ) {
36 83         64 $n++;
37 83         202 $lap->{each} = [gettimeofday];
38 83 100       228 if (wantarray) {
    100          
39 12         12 my @ret = eval { $code->($n) };
  12         20  
40 12 100       95 unless ($retry_if->(@ret)) {
41 3         24 return @ret;
42             }
43 9         11 _timeout($timeout, $lap);
44             }
45             elsif (not defined wantarray) {
46 21         24 eval { $code->($n) };
  21         36  
47 21 100       140 unless ($retry_if->()) {
48 2         10 return;
49             }
50 19         22 _timeout($timeout, $lap);
51             }
52             else {
53 50         54 my $ret = eval { $code->($n) };
  50         101  
54 50 100       1922216 unless ($retry_if->($ret)) {
55 4         21 return $ret;
56             }
57 46         127 _timeout($timeout, $lap);
58             }
59 71 100       6055457 sleep $delay if $times; # Do not sleep in last time
60 71         162 _timeout($timeout, $lap);
61             }
62 3 100       381 die $err if $err;
63             }
64              
65             sub _timeout {
66 145     145   171 my ($timeout, $lap) = @_;
67              
68 145 100 100     397 if ( $timeout->{each}
69             && tv_interval($lap->{each}) > $timeout->{each} ) {
70 3         227 die 'retry timeout: each time';
71             }
72              
73 142 100 100     459 if ( $timeout->{total}
74             && tv_interval($lap->{start}) > $timeout->{total} ) {
75 3         112 die 'retry timeout: total time';
76             }
77              
78 139         471 return;
79             }
80              
81             1;
82              
83             __END__