NAME
Retry::Policy - Simple retry wrapper with exponential backoff and jitter
SYNOPSIS
use Retry::Policy;
my $p = Retry::Policy->new(
max_attempts => 5,
base_delay_ms => 100,
max_delay_ms => 10_000,
jitter => 'full',
);
my $value = $p->run(sub {
my ($attempt) = @_;
die "transient\n" if $attempt < 3;
return "ok";
});
DESCRIPTION
Small, dependency-light retry helper for backend and system code where transient failures are expected.
DESIGN NOTES
Exponential backoff with a maximum cap is a common production default for transient failures.
Full jitter helps avoid synchronized retries (thundering herd) across multiple workers or hosts.
Defaults are intentionally conservative; callers should tune retry behavior per dependency (database, HTTP service, filesystem, etc.).
Validation is strict: invalid configurations fail fast rather than producing undefined retry behavior.
PRACTICAL USE CASES
Retry a flaky HTTP call (transient network or service errors)
use Retry::Policy;
my $p = Retry::Policy->new(
max_attempts => 6,
base_delay_ms => 200,
max_delay_ms => 5000,
retry_on => sub {
my ($err) = @_;
return ($err =~ /timeout|temporarily unavailable|connection reset/i) ? 1 : 0;
},
);
my $body = $p->run(sub {
# Replace this block with your HTTP client of choice
die "timeout\n" if rand() < 0.2;
return "ok";
});
Retry a database connection (DBI)
use DBI;
use Retry::Policy;
my $p = Retry::Policy->new(
max_attempts => 5,
base_delay_ms => 250,
max_delay_ms => 8000,
retry_on => sub {
my ($err) = @_;
return ($err =~ /server has gone away|lost connection|timeout/i) ? 1 : 0;
},
);
my $dbh = $p->run(sub {
my $dbh = DBI->connect($dsn, $user, $pass, { RaiseError => 1, PrintError => 0 });
return $dbh;
});
Retry acquiring a lock or contended resource
use Fcntl qw(:flock);
use Retry::Policy;
my $p = Retry::Policy->new(
max_attempts => 20,
base_delay_ms => 50,
max_delay_ms => 1000,
retry_on => sub { 1 }, # lock contention is typically transient
);
$p->run(sub {
open my $fh, ">>", "/tmp/my.lock" or die "open lock: $!\n";
flock($fh, LOCK_EX | LOCK_NB) or die "lock busy\n";
# work while lock held
return 1;
});
LICENSE
Same terms as Perl itself.