NAME

Try::ALRM - Structured retry and timeout handling using CORE::alarm

DESCRIPTION

Try::ALRM provides try/catch-like semantics around alarm.

Internally, this module uses Perl prototypes to coerce lexical blocks into CODE references, in the same spirit as Try::Tiny. The public syntax remains compact:

retry { ... }
ALRM  { ... }
finally { ... }
timeout => 5,
tries   => 10;

Timeouts are handled by a localized $SIG{ALRM} handler. When the alarm fires, the optional ALRM block is executed and the current attempt is immediately aborted. If retry attempts remain, retry continues with the next attempt.

The active alarm is always cleared before control leaves the attempt, whether the block succeeds, times out, or dies for another reason.

EXPORTS

This module exports six keywords.

try_once BLOCK

Runs BLOCK once with an alarm set to the current timeout value.

try_once is equivalent to:

retry { ... } tries => 1;

If an alarm fires, the optional ALRM block is executed, followed by finally if provided.

retry BLOCK

Runs BLOCK up to tries times. Each attempt receives the current attempt number via @_.

Retries stop when either:

  • The block completes without an alarm

  • The retry limit is reached

  • The block dies for a non-timeout reason

If BLOCK dies for a non-timeout reason, finally is still executed before the original exception is rethrown.

ALRM BLOCK

Optional handler executed when an alarm fires.

Receives the current attempt number:

ALRM {
  my ($attempt) = @_;
  warn "Attempt $attempt timed out\n";
}

After ALRM runs, the current attempt is aborted and retry moves to the next attempt if one remains.

finally BLOCK

Optional block executed unconditionally after all attempts are complete, or after a non-timeout exception interrupts retry processing.

Receives:

my ($attempts, $successful) = @_;

$attempts is the number of attempts actually made.

$successful is true if one attempt completed without timing out or throwing an exception.

If both the main block and finally die, the main block's exception is preserved and rethrown.

timeout INT

Getter/setter for the default timeout in seconds.

May also be supplied as a trailing modifier:

try_once { ... } timeout => 2;

The value must be an integer greater than or equal to 1.

tries INT

Getter/setter for the default retry limit.

May also be supplied as a trailing modifier:

retry { ... } tries => 5;

The value must be an integer greater than or equal to 1.

PACKAGE ENVIRONMENT

The following package variables are exposed:

  • $Try::ALRM::TIMEOUT

  • $Try::ALRM::TRIES

They may be set globally through the timeout and tries setters.

During a retry or try_once block, trailing timeout and tries modifiers are localized so calls to timeout and tries inside user blocks reflect the active values.

TRAILING MODIFIERS

Trailing modifiers are written as key/value pairs after the final block:

retry {
  ...
}
ALRM {
  ...
}
finally {
  ...
}
timeout => 5,
tries   => 10;

Valid trailing keys are:

  • ALRM

  • finally

  • timeout

  • tries

Unknown keys, duplicate keys, invalid timeout values, and invalid retry counts are rejected.

BUGS

Almost certainly.

This module was motivated both by curiosity about Perl prototypes and by the practical question of whether ALRM could be treated as a localized exception.

Mileage may vary. Please report issues.

PERL ADVENT 2022

| \__ `\O/  `--  {}    \}    {/    {}    \}    {/    {}    \} 
\    \_(~)/_..___/=____/=____/=____/=____/=____/=____/=____/=*
 \=======/    //\\  >\/> || \>  //\\  >\/> || \>  //\\  >\/> 
----`---`---  `` `` ```` `` ``  `` `` ```` `` ``  ````  ````

ACKNOWLEDGEMENTS

"This module is dedicated to the least of you amongst us, the defenseless unborn, and to all of those who have died suddenly."

AUTHOR

Brett Estrade (OODLER) <oodler@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2022-Present by Brett Estrade

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.