Action-Retry
view release on metacpan or search on metacpan
lib/Action/Retry.pm view on Meta::CPAN
if (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
C<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
=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
use 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
}
{
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.250 second using v1.01-cache-2.11-cpan-65fba6d93b7 )