App-AlgorithmBackoffUtils

 view release on metacpan or  search on metacpan

lib/App/AlgorithmBackoffUtils.pm  view on Meta::CPAN

        {url => 'pm:Algorithm::Backoff::LIMD'},
    ],
};
sub retry_limd {
    _retry("LIMD", {@_});
}

$SPEC{retry_mild} = {
    v => 1.1,
    summary => 'Retry a command with MILD (multiplicative increase, linear decrease) backoff',
    args => {
        %args_retry_common,
        %{ $Algorithm::Backoff::MILD::SPEC{new}{args} },
    },
    features => {
        dry_run => 1,
    },
    links => [
        {url => 'pm:Algorithm::Backoff::MILD'},
    ],
};
sub retry_mild {
    _retry("MILD", {@_});
}

$SPEC{retry_mimd} = {
    v => 1.1,
    summary => 'Retry a command with MIMD (multiplicative increase, multiplicative decrease) backoff',
    args => {
        %args_retry_common,
        %{ $Algorithm::Backoff::MIMD::SPEC{new}{args} },
    },
    features => {
        dry_run => 1,
    },
    links => [
        {url => 'pm:Algorithm::Backoff::MIMD'},
    ],
};
sub retry_mimd {
    _retry("MIMD", {@_});
}

$SPEC{show_backoff_delays} = {
    v => 1.1,
    summary => 'Show backoff delays',
    args => {
        %arg_algorithm,
        %args_algo_attrs,
        logs => {
            summary => 'List of failures or successes',
            schema => ['array*', of=>'str*', 'x.perl.coerce_rules'=>['From_str::comma_sep']],
            'x.name.is_plural' => 1,
            'x.name.singular' => 'log',
            req => 1,
            pos => 0,
            slurpy => 1,
            description => <<'_',

A list of 0's (to signify failure) or 1's (to signify success). Each
failure/success can be followed by `:TIMESTAMP` (unix epoch) or `:+SECS` (number
of seconds after the previous log), or the current timestamp will be assumed.
Examples:

    0 0 0 0 0 0 0 0 0 0 1 1 1 1 1

(10 failures followed by 5 successes).

    0 0:+2 0:+4 0:+6 1

(4 failures, 2 seconds apart, followed by immediate success.)

_
        },
    },
    features => {
        dry_run => 1,
    },
    links => [
        {url => 'pm:Algorithm::Backoff::Fibonacci'},
    ],
};
sub show_backoff_delays {
    my %args = @_;

    my $algo = $args{algorithm} or return [400, "Please specify algorithm"];
    my $algo_args = ${"Algorithm::Backoff::$algo\::SPEC"}{new}{args};

    my %algo_attrs;
    for my $arg (keys %args_algo_attrs) {
        my $argspec = $args_algo_attrs{$arg};
        next unless grep {
            $_ eq 'category:common-to-all-algorithms' ||
            $_ eq lc("category:$algo-algorithm")
        } @{ $argspec->{tags} };
        if (exists $args{$arg}) {
            $algo_attrs{$arg} = $args{$arg};
        }
    }
    #use DD; dd \%args_algo_attrs;
    #use DD; dd \%algo_attrs;
    my $ab = "Algorithm::Backoff::$algo"->new(%algo_attrs);

    my @delays;
    my $time = time();
    my $i = 0;
    for my $log (@{ $args{logs} }) {
        $i++;
        $log =~ /\A([01])(?::(\+)?(\d+))?\z/ or
            return [400, "Invalid log#$i syntax '$log', must be 0 or 1 followed by :TIMESTAMP or :+SECS"];
        if ($2) {
            $time += $3;
        } elsif (defined $3) {
            $time = $3;
        }
        my $delay;
        if ($1) {
            $delay = $ab->success($time);
        } else {
            $delay = $ab->failure($time);
        }

lib/App/AlgorithmBackoffUtils.pm  view on Meta::CPAN

again right after the previous failure() (i.e. specify the same timestamp).
failure() will then return ~2+2 = 4 seconds. On the other hand, if you waited 2
seconds before calling failure() again (i.e. specify the timestamp that is 2
seconds larger than the previous timestamp), failure() will return 2 seconds.
And if you waited 4 seconds or more, failure() will return 0.

=item * B<delay> => I<ufloat>

Number of seconds to wait after a failure.

=item * B<delay_increment_on_failure> => I<float>

How much to add to previous delay, in seconds, upon failure (e.g. 5).

=item * B<delay_increment_on_success> => I<float>

How much to add to previous delay, in seconds, upon success (e.g. -5).

=item * B<delay_multiple_on_failure> => I<ufloat>

How much to multiple previous delay, upon failure (e.g. 1.5).

=item * B<delay_multiple_on_success> => I<ufloat>

How much to multiple previous delay, upon success (e.g. 0.5).

=item * B<delay_on_success> => I<ufloat> (default: 0)

Number of seconds to wait after a success.

=item * B<exponent_base> => I<ufloat> (default: 2)

=item * B<initial_delay> => I<ufloat>

Initial delay for the first attempt after failure, in seconds.

=item * B<initial_delay1> => I<ufloat>

Initial delay for the first attempt after failure, in seconds.

=item * B<initial_delay2> => I<ufloat>

Initial delay for the second attempt after failure, in seconds.

=item * B<jitter_factor> => I<float>

How much to add randomness.

If you set this to a value larger than 0, the actual delay will be between a
random number between original_delay * (1-jitter_factor) and original_delay *
(1+jitter_factor). Jitters are usually added to avoid so-called "thundering
herd" problem.

The jitter will be applied to delay on failure as well as on success.

=item * B<logs>* => I<array[str]>

List of failures or successes.

A list of 0's (to signify failure) or 1's (to signify success). Each
failure/success can be followed by C<:TIMESTAMP> (unix epoch) or C<:+SECS> (number
of seconds after the previous log), or the current timestamp will be assumed.
Examples:

 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1

(10 failures followed by 5 successes).

 0 0:+2 0:+4 0:+6 1

(4 failures, 2 seconds apart, followed by immediate success.)

=item * B<max_actual_duration> => I<ufloat> (default: 0)

Maximum number of seconds for all of the attempts (0 means unlimited).

If set to a positive number, will limit the number of seconds for all of the
attempts. This setting is used to limit the amount of time you are willing to
spend on a task. For example, when using the Exponential strategy of
initial_delay=3 and max_attempts=10, the delays will be 3, 6, 12, 24, ... If
failures are logged according to the suggested delays, and max_actual_duration
is set to 21 seconds, then the third failure() will return -1 instead of 24
because 3+6+12 >= 21, even though max_attempts has not been exceeded.

=item * B<max_attempts> => I<uint> (default: 0)

Maximum number consecutive failures before giving up.

0 means to retry endlessly without ever giving up. 1 means to give up after a
single failure (i.e. no retry attempts). 2 means to retry once after a failure.
Note that after a success, the number of attempts is reset (as expected). So if
max_attempts is 3, and if you fail twice then succeed, then on the next failure
the algorithm will retry again for a maximum of 3 times.

=item * B<max_delay> => I<ufloat>

Maximum delay time, in seconds.

=item * B<min_delay> => I<ufloat> (default: 0)

Maximum delay time, in seconds.


=back

Special arguments:

=over 4

=item * B<-dry_run> => I<bool>

Pass -dry_run=E<gt>1 to enable simulation mode.

=back

Returns an enveloped result (an array).

First element (status) is an integer containing HTTP status code
(200 means OK, 4xx caller error, 5xx function error). Second element
(msg) is a string containing error message, or 'OK' if status is
200. Third element (payload) is optional, the actual result. Fourth



( run in 1.425 second using v1.01-cache-2.11-cpan-39bf76dae61 )