Action-Retry
view release on metacpan or search on metacpan
lib/Action/Retry.pm view on Meta::CPAN
8990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138if
(
my
$timestamp
=
$self
->_needs_sleeping_until) {
# we can't retry until we have waited enough time
my
(
$seconds
,
$microseconds
) = gettimeofday;
$seconds
* 1000 +
int
(
$microseconds
/ 1000) >=
$timestamp
or
return
;
$self
->_needs_sleeping_until(0);
$self
->strategy->next_step;
}
my
$error
;
my
@attempt_result
;
my
$attempt_result
;
my
$wantarray
;
if
(
wantarray
) {
$wantarray
= 1;
@attempt_result
=
eval
{
$self
->attempt_code->(
@_
) };
$error
= $@;
}
elsif
( !
defined
wantarray
) {
eval
{
$self
->attempt_code->(
@_
) };
$error
= $@;
}
else
{
$attempt_result
=
eval
{
$self
->attempt_code->(
@_
) };
$error
= $@;
}
my
$h
= {
action_retry
=>
$self
,
attempt_result
=> (
$wantarray
? \
@attempt_result
:
$attempt_result
),
attempt_parameters
=> \
@_
,
};
$self
->retry_if_code->(
$error
,
$h
)
or
$self
->strategy->
reset
, $@ =
$error
,
return
(
$wantarray
?
@attempt_result
:
$attempt_result
);
if
(!
$self
->strategy->needs_to_retry) {
$self
->strategy->
reset
;
$self
->has_on_failure_code
and
return
$self
->on_failure_code->(
$error
,
$h
);
return
;
}
if
(
$self
->non_blocking) {
my
(
$seconds
,
$microseconds
) = gettimeofday;
$self
->_needs_sleeping_until(
$seconds
* 1000 +
int
(
$microseconds
/ 1000) +
$self
->strategy->compute_sleep_time);
}
else
{
usleep(
$self
->strategy->compute_sleep_time * 1000);
$self
->strategy->next_step;
}
lib/Action/Retry.pm view on Meta::CPAN
305306307308309310311312313314315316317318319320321322323324C<retry_if_code>
return
value will be interpreted as a boolean : true
return
value means the execution of C<attempt_code> was a failure and it needs to be
retried. False means it went well.
Here is an example of code that gets the arguments properly:
my
$action
= Action::Retry->new(
attempt_code
=>
sub
{ do_stuff; } )->run();
attempt_code
=>
sub
{
map
{
$_
* 2 }
@_
}
retry_if_code
=>
sub
{
my
(
$error
,
$h
) =
@_
;
my
$attempt_code_result
=
$h
->{attempt_result};
my
$attempt_code_params
=
$h
->{attempt_parameters};
my
@results
=
@$attempt_code_result
;
# will contains (2, 4);
my
@original_parameters
=
@$attempt_code_params
;
# will contains (1, 2);
lib/Action/Retry.pm view on Meta::CPAN
378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415=head2 run
Does the following:
=over
=item step 1
Runs the C<attempt_code> CodeRef in the proper context in an eval {} block,
saving C<$@> in C<$error>.
=item step 2
Runs the C<retry_if_code> CodeRef in scalar context, giving it as arguments
C<$error>, and the return values of C<attempt_code>. If it returns true, we
consider that it was a failure, and move to step 3. Otherwise, we consider it
means success, and return the return values of C<attempt_code>.
=item step 3
Ask the C<strategy> if it's still useful to retry. If yes, sleep accordingly,
and go back to step 2. If not, go to step 4.
=item step 4
Runs the C<on_failure_code> CodeRef in the proper context, giving it as
arguments C<$error>, and the return values of C<attempt_code>, and returns the
results back to the caller.
=back
Arguments passed to C<run()> will be passed to C<attempt_code>. They will also
passed to C<on_failure_code> as well if the case arises.
=head2 retry
retry { ..code.. } some => 'arguments';
t/check_params.t view on Meta::CPAN
23456789101112131415161718192021222324252627use
strict;
use
warnings;
use
Test::More;
{
my
$var
= 0;
my
$action
= Action::Retry->new(
attempt_code
=>
sub
{
my
(
$val
) =
@_
;
$var
++;
die
"plop\n"
if
$var
< 5;
return
$var
+
$val
; },
retry_if_code
=>
sub
{
my
(
$error
,
$h
) =
@_
;
chomp
$error
;
if
(
$var
< 5) {
is
$error
,
"plop"
;
return
1;
}
else
{
ok !
$error
;
is
$h
->{attempt_result},
$var
+
$h
->{attempt_parameters}[0];
return
0;
}
},
strategy
=> {
Fibonacci
=> {
initial_term_index
=> 0,
multiplicator
=> 10 } },
);
my
$result
=
$action
->run(2);
is(
$result
, 7);
}
t/fibonacci.t view on Meta::CPAN
48495051525354555657585960616263646566}
{
my
@expected
= (5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610);
my
@got
;
my
$var
= 0;
my
$acc
= 0;
my
$action
= Action::Retry->new(
attempt_code
=>
sub
{
my
(
$val
) =
@_
;
$acc
+=
$val
;
$var
++;
die
"plop"
},
retry_if_code
=>
sub
{
my
(
$error
,
$h
) =
@_
;
push
@got
,
$h
->{action_retry}->strategy->compute_sleep_time;
$error
; },
strategy
=> {
Fibonacci
=> {
initial_term_index
=> 5,
multiplicator
=> 1 } },
);
$action
->run(2);
is(
$var
, 11);
is(
$acc
, 22);
is_deeply(\
@got
, \
@expected
,
'starting with an initial_term_index works'
);
}
done_testing;
( run in 0.356 second using v1.01-cache-2.11-cpan-26ccb49234f )