Algorithm-Backoff-RetryTimeouts

 view release on metacpan or  search on metacpan

CHANGES  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
Changelog for Algorithm-Backoff-RetryTimeouts
 
v1.0.0 2021-02-11T22:07:03
 - Fix POD error (Brendan Byrd)
 - Create distribution files (Andrew Hewus Fresh)
 - Set _attempts / _last_timestamp even on max duration/attempt failures
   (Brendan Byrd)
 - Fix unnecessary delays during the first failure (Brendan Byrd)
 - Add timeout_jitter_factor with a default of 10% (Brendan Byrd)
 - Create Algorithm::Backoff::RetryTimeouts and unit test (Brendan Byrd)
 - Initial Commit (Brendan Byrd)

README  view on Meta::CPAN

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
     * Exponential backoff - A sqrt(2) exponential delay keeps single
     retries from waiting too long, while spreading out repeated retries
     that may fail too quickly and run out of max attempts. This also
     decreases the congestion that happens with repeated attempts.
 
     * Jitter - Adding random jitter to the retry delays solves for the
     Thundering Herd problem.
 
     * Adjustable timeouts - Providing an adjustable timeout after each
     request solves the opposite problem of exponential backoffs: slower,
     unresponsive errors that gobble up all of the max duration time in
     one go. Each new timeout is a certain percentage of the time left.
 
Typical scenario
 
   Here's an example scenario of the algorithm with existing defaults:
 
       $retry_algo is created, and timer starts
    
       Initial timeout is 25s
   

lib/Algorithm/Backoff/RetryTimeouts.pm  view on Meta::CPAN

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#pod max attempts.  This also decreases the congestion that happens with repeated attempts.
#pod
#pod =item *
#pod
#pod B<Jitter> - Adding random jitter to the retry delays solves for the Thundering Herd
#pod problem.
#pod
#pod =item *
#pod
#pod B<Adjustable timeouts> - Providing an adjustable timeout after each request solves the
#pod opposite problem of exponential backoffs: slower, unresponsive errors that gobble up all
#pod of the max duration time in one go.  Each new timeout is a certain percentage of the time
#pod left.
#pod
#pod =back
#pod
#pod =head2 Typical scenario
#pod
#pod Here's an example scenario of the algorithm with existing defaults:
#pod
#pod     $retry_algo is created, and timer starts

lib/Algorithm/Backoff/RetryTimeouts.pm  view on Meta::CPAN

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
max attempts.  This also decreases the congestion that happens with repeated attempts.
 
=item *
 
B<Jitter> - Adding random jitter to the retry delays solves for the Thundering Herd
problem.
 
=item *
 
B<Adjustable timeouts> - Providing an adjustable timeout after each request solves the
opposite problem of exponential backoffs: slower, unresponsive errors that gobble up all
of the max duration time in one go.  Each new timeout is a certain percentage of the time
left.
 
=back
 
=head2 Typical scenario
 
Here's an example scenario of the algorithm with existing defaults:
 
    $retry_algo is created, and timer starts

t/00-report-prereqs.t  view on Meta::CPAN

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
my $static_prereqs = do './t/00-report-prereqs.dd';
 
# Merge all prereqs (either with ::Prereqs or a hashref)
my $full_prereqs = _merge_prereqs(
    ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ),
    $static_prereqs
);
 
# Add dynamic prereqs to the included modules list (if we can)
my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml';
my $cpan_meta_error;
if ( $source && $HAS_CPAN_META
    && (my $meta = eval { CPAN::Meta->load_file($source) } )
) {
    $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs);
}
else {
    $cpan_meta_error = $@;    # capture error from CPAN::Meta->load_file($source)
    $source = 'static metadata';
}
 
my @full_reports;
my @dep_errors;
my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs;
 
# Add static includes into a fake section
for my $mod (@include) {
    $req_hash->{other}{modules}{$mod} = 0;
}
 
for my $phase ( qw(configure build test runtime develop other) ) {
    next unless $req_hash->{$phase};
    next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING});

t/00-report-prereqs.t  view on Meta::CPAN

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
    my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required";
 
    if ($prefix) {
        my $have = MM->parse_version( File::Spec->catfile($prefix, $file) );
        $have = "undef" unless defined $have;
        push @reports, [$mod, $want, $have];
 
        if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) {
            if ( $have !~ /\A$lax_version_re\z/ ) {
                push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)";
            }
            elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) {
                push @dep_errors, "$mod version '$have' is not in required range '$want'";
            }
        }
    }
    else {
        push @reports, [$mod, $want, "missing"];
 
        if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) {
            push @dep_errors, "$mod is not installed ($req_string)";
        }
    }
}
 
if ( @reports ) {
    push @full_reports, "=== $title ===\n\n";
 
    my $ml = _max( map { length $_->[0] } @reports );
    my $wl = _max( map { length $_->[1] } @reports );
    my $hl = _max( map { length $_->[2] } @reports );

t/00-report-prereqs.t  view on Meta::CPAN

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
            push @full_reports, "\n";
        }
    }
}
 
if ( @full_reports ) {
    diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports;
}
 
if ( $cpan_meta_error || @dep_errors ) {
    diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n";
}
 
if ( $cpan_meta_error ) {
    my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml';
    diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n";
}
 
if ( @dep_errors ) {
    diag join("\n",
        "\nThe following REQUIRED prerequisites were not satisfied:\n",
        @dep_errors,
        "\n"
    );
}
 
pass;
 
# vim: ts=4 sts=4 sw=4 et:



( run in 0.649 second using v1.01-cache-2.11-cpan-95122f20152 )