File Coverage

blib/lib/Throttle/Adaptive.pm
Criterion Covered Total %
statement 28 32 87.5
branch 4 6 66.6
condition 3 7 42.8
subroutine 7 7 100.0
pod 2 3 66.6
total 44 55 80.0


line stmt bran cond sub pod time code
1 1     1   67694 use strict;
  1         8  
  1         29  
2 1     1   5 use warnings;
  1         1  
  1         54  
3             package Throttle::Adaptive;
4             our $AUTHORITY = 'cpan:TVDW';
5             $Throttle::Adaptive::VERSION = '0.001';
6             # ABSTRACT: implementation of the "adaptive throttling" algorithm by Google
7              
8 1     1   554 use Time::HiRes qw/CLOCK_MONOTONIC/;
  1         1339  
  1         4  
9              
10             sub new {
11 1     1 0 84 my ($class, %args)= @_;
12             return bless {
13             ratio => $args{ratio} || 2,
14 1   50     12 time => $args{time} || 120,
      50        
15              
16             window => [],
17             window_success => 0,
18             window_total => 0,
19             }, $class;
20             }
21              
22             sub _process_window {
23 400     400   614 my ($self)= @_;
24 400         1055 my $now= Time::HiRes::clock_gettime(CLOCK_MONOTONIC);
25 400   33     1393 while (@{$self->{window}} && $self->{window}[0][0] < $now) {
  400         1660  
26 0         0 my $entry= shift @{$self->{window}};
  0         0  
27 0         0 $self->{window_total}--;
28 0 0       0 $self->{window_success}-- if $entry->[1];
29             }
30 400         640 return;
31             }
32              
33             sub should_fail {
34 400     400 1 53387 my ($self)= @_;
35 400         871 $self->_process_window;
36              
37 400         1079 my $fail= ( rand() < (($self->{window_total} - ($self->{ratio} * $self->{window_success})) / ($self->{window_total} + 1)) );
38 400 100       792 $self->count(1) if $fail;
39 400         964 return $fail;
40             }
41              
42             sub count {
43 673     673 1 1675 my ($self, $error)= @_;
44 673         873 my $success= !$error;
45              
46 673         862 $self->{window_total}++;
47 673         895 push @{$self->{window}}, [ Time::HiRes::clock_gettime(CLOCK_MONOTONIC)+$self->{time}, $success ];
  673         1255  
48 673 100       3192 $self->{window_success}++ if $success;
49 673         1117 return;
50             }
51              
52             1;
53              
54             __END__