NAME
Action::Retry - Module to try to perform an action, with various ways of retrying and sleeping between retries.
VERSION
version 0.16
SYNOPSIS
# Simple usage, will attempt to run the code, retrying if it dies, retrying
# 10 times max, sleeping 1 second between retries
# functional interface
use Action::Retry qw(retry);
retry { do_stuff };
# OO interface
use Action::Retry;
Action::Retry->new( attempt_code => sub { do_stuff; } )->run();
# Same, but sleep time is doubling each time
# OO interface
my $action = Action::Retry->new(
attempt_code => sub { ... },
strategy => 'Linear',
);
$action->run();
# functional interface
retry { ... } strategy => 'Linear';
# Same, but sleep time is following the Fibonacci sequence
# OO interface
my $action = Action::Retry->new(
attempt_code => sub { ... },
strategy => 'Fibonacci',
);
$action->run();
# functional interface
retry { ... } strategy => 'Fibonacci';
# The code to check if the attempt succeeded can be customized. Strategies
# can take arguments. Code on failure can be specified.
# OO way
my $action = Action::Retry->new(
attempt_code => sub { ... },
retry_if_code => sub { $_[0] =~ /Connection lost/ || $_[1] > 20 },
strategy => { Fibonacci => { multiplicator => 2000,
initial_term_index => 3,
max_retries_number => 5,
}
},
on_failure_code => sub { say "Given up retrying" },
);
$action->run();
# functional way
retry { ...}
retry_if_code => sub { ... },
strategy => { Fibonacci => { multiplicator => 2000,
initial_term_index => 3,
max_retries_number => 5,
}
},
on_failure_code => sub { ... };
# Retry code in non-blocking way
# OO way
my $action = Action::Retry->new(
attempt_code => sub { ...},
non_blocking => 1,
);
while (1) {
# if the action failed, it doesn't sleep
# next time it's called, it won't do anything until it's time to retry
$action->run();
# do something else while time goes on
}
There is no functional way of doing that, for now.
ATTRIBUTES
attempt_code
ro, CodeRef, required
The code to run to attempt doing the action. Will be evaluated taking care of the caller's context.
retry_if_code
ro, CodeRef
The code to run to check if we need to retry the action. It will be given as first argument, $@, then as following arguments the return values of the execution of attempt_code
.
True return value means the execution of attempt_code
was a failure and it needs to be retried. False means it went well.
Defaults to:
# Returns true if there were an exception evaluating to something true
sub { $_[0] }
on_failure_code
ro, CodeRef, optional
If given, the code to run when retries are given up.
strategy
ro, defaults to 'Constant'
The strategy for managing retrying times, sleeping, and giving up. It must be an object that does the Action::Retry::Strategy role.
This attribute has a coercion from strings and hashrefs. If you pass a string, it will be treated as a class name (under Action::Retry::Strategy::
, unless it is prefxed with a +
) to instantiate.
If you pass a hashref, the first key will be treated as a class name as above, and the value of that key will be treated as the args to pass to new
.
Some existing stragies classes are Action::Retry::Strategy::Constant, Action::Retry::Strategy::Fibonacci, Action::Retry::Strategy::Linear.
Defaults to 'Constant'
non_blocking
ro, defaults to 0
If true, the instance will be in a pseudo non blocking mode. In this mode, the run()
function behaves a bit differently: instead of sleeping between retries, the run()
command will immediately return. Subsequent call to run()
will immediately return, until the time to sleep has been elapsed. This allows to do things like that:
my $action = Action::Retry->new( ... , non_blocking => 1 );
while (1) {
# if the action failed, it doesn't sleep
# next time it's called, it won't do anything until it's time to retry
$action->run();
# do something else while time goes on
}
If you need a more advanced non blocking mode and callbacks, then look at AnyEvent::Retry
METHODS
run
Does the following:
- step 1
-
Runs the
attempt_code
CodeRef in the proper context in an eval {} block, saving$@
in$error
. - step 2
-
Runs the
retry_if_code
CodeRef in scalar context, giving it as arguments$error
, and the return values ofattempt_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 ofattempt_code
. - step 3
-
Ask the
strategy
if it's still useful to retry. If yes, sleep accordingly, and go back to step 2. If not, go to step 4. - step 4
-
Runs the
on_failure_code
CodeRef in the proper context, giving it as arguments$error
, and the return values ofattempt_code
, and returns the results back to the caller.
SRATEGIES
Here are the strategies currently included by default. Check their documentation for more details.
- Action::Retry::Strategy::Constant
-
Provides a simple constant sleep time strategy
- Action::Retry::Strategy::Fibonacci
-
Provides an incremental constant sleep time strategy following Fibonacci sequence
- Action::Retry::Strategy::Linear
-
Provides a linear incrementing sleep time strategy
SEE ALSO
I created this module because the other related modules I found didn't exactly do what I wanted. Here is the list and why:
- Retry
-
No custom checking code. No retry strategies. Can't sleep under one second. No non-blocking mode. No custom failure code.
- Sub::Retry
-
No retry strategies. Can't sleep under one second. Retry code is passed the results of the attempt code, but not the exception. No non-blocking mode. No custom failure code.
- Attempt
-
No custom checking code. Strange exception catching behavior. No retry strategies. No non-blocking mode. No custom failure code.
- AnyEvent::Retry
-
Depends on AnyEvent, and Moose. Strategies are less flexibles, and they don't have sleep timeouts (only max tries).
AUTHOR
Damien "dams" Krotkine
COPYRIGHT AND LICENSE
This software is copyright (c) 2013 by Damien "dams" Krotkine.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.