1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 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 155 156 157 158
|
package Net::Twitter::Role::RetryOnError;
$Net::Twitter::Role::RetryOnError::VERSION = '4.01043';
use Moose::Role;
use namespace::autoclean;
use Time::HiRes;
requires '_send_request';
=head1 NAME
Net::Twitter::Role::RetryOnError - Retry Twitter API calls on error
=head1 VERSION
version 4.01043
=head1 SYNOPSIS
use Net::Twitter;
$nt = Net::Twitter->new(
traits => ['API::RESTv1_1', 'RetryOnError']
max_retries => 3,
);
=head1 DESCRIPTION
Temporary errors are not uncommon when calling the Twitter API. When applied
to L<Net::Twitter> this role will provide automatic retries of API calls in a very
configurable way.
It only retries when the response status code is E<gt>= 500. Other error codes
indicate a permanent error. If the maximum number of retries is reached,
without success, an exception is thrown, as usual.
=head1 OPTIONS
This role adds the following options to C<new>:
=over 4
=item initial_retry_delay
A floating point number specifying the initial delay, after an error, before
retrying. Default: 0.25 (250 milliseconds).
=cut
has initial_retry_delay => (
is => 'rw',
isa => 'Num',
default => 0.250, # 250 milliseconds
);
=item max_retry_delay
A floating point number specifying the maximum delay between retries. Default: 4.0
=cut
has max_retry_delay => (
is => 'rw',
isa => 'Num',
default => 4.0, # 4 seconds
);
=item retry_delay_multiplier
On the second and subsequent retries, a new delay is calculated by multiplying the previous
delay by C<retry_delay_multiplier>. Default: 2.0
=cut
has retry_delay_multiplier => (
is => 'rw',
isa => 'Num',
default => 2, # double the prior delay
);
=item max_retries
The maximum number of consecutive retries before giving up and throwing an exception.
If set to 0, it the API call will be retried indefinitely. Default 5.
=cut
has max_retries => (
is => 'rw',
isa => 'Int',
default => 5, # 0 = try forever
);
=item retry_delay_code
A code reference that will be called to handle the delay. It is passed a
single argument: a floating point number specifying the number of seconds to
delay. By default, L<Time::HiRes/sleep> is called.
If you're using a non-blocking user agent, like L<Coro::LWP>, you should use
this option to provide a non-blocking delay.
=cut
has retry_delay_code => (
is => 'rw',
isa => 'CodeRef',
default => sub {
sub { Time::HiRes::sleep(shift) };
},
);
=back
=cut
around _send_request => sub {
my ( $orig, $self, $msg ) = @_;
my $is_oauth = do {
my $auth_header = $msg->header('authorization');
$auth_header && $auth_header =~ /^OAuth /;
};
my $delay = $self->initial_retry_delay;
my $retries = $self->max_retries;
while () {
my $res = $self->$orig($msg);
return $res if $res->is_success || $retries-- == 0 || $res->code < 500;
$self->retry_delay_code->($delay);
$delay *= $self->retry_delay_multiplier;
$delay = $self->max_retry_delay if $delay > $self->max_retry_delay;
# If this is an OAuth request, we need a new Authorization header
# (the nonce may be invalid, now).
$self->_add_authorization_header($msg) if $is_oauth;
}
};
1;
__END__
=head1 AUTHOR
Marc Mims <marc@questright.com>
=head1 COPYRIGHT
Copyright (c) 2016 Marc Mims
=head1 LICENSE
This library is free software and may be distributed under the same terms as perl itself.
=cut
|