File Coverage

blib/lib/POE/Component/ResourcePool/Resource/TokenBucket.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package POE::Component::ResourcePool::Resource::TokenBucket;
4 1     1   23850 use MooseX::POE;
  0            
  0            
5              
6             with qw(POE::Component::ResourcePool::Resource);
7              
8             use Tie::RefHash::Weak;
9             use POE;
10             use Algorithm::TokenBucket;
11              
12             our $VERSION = "0.01";
13              
14             with qw(MooseX::POE::Aliased);
15              
16             sub shutdown { shift->clear_alias }
17              
18             has token_bucket => (
19             isa => "Algorithm::TokenBucket",
20             is => "ro",
21             init_arg => undef,
22             lazy_build => 1,
23             );
24              
25             sub _build_token_bucket {
26             my $self = shift;
27            
28             Algorithm::TokenBucket->new( $self->rate, $self->burst );
29             }
30              
31             has rate => (
32             isa => "Num",
33             is => "ro",
34             required => 1,
35             );
36              
37             has burst => (
38             isa => "Num",
39             is => "ro",
40             required => 1,
41             );
42              
43             has _requests => (
44             isa => "HashRef",
45             is => "ro",
46             init_arg => undef,
47             default => sub { Tie::RefHash::Weak::fieldhash my %h },
48             );
49              
50             sub could_allocate {
51             my ( $self, $pool, $request, $value ) = @_;
52              
53             return $value <= $self->burst;
54             }
55              
56             sub try_allocating {
57             my ( $self, $pool, $request, $value ) = @_;
58              
59             if ( my $until = $self->token_bucket->until($value) ) {
60             $self->yield( delay_notification => $until, $pool, $request, $value );
61             return;
62             } else {
63             return $value;
64             }
65             }
66              
67             sub finalize_allocation {
68             my ( $self, $pool, $request, $value ) = @_;
69              
70             $self->token_bucket->count($value);
71              
72             return $value;
73             }
74              
75             sub free_allocation {
76             return;
77             }
78              
79             sub forget_request {
80             my ( $self, $pool, $request ) = @_;
81              
82             if ( my $alarm = $self->_requests->{$request} ) {
83             $poe_kernel->alarm_remove($alarm);
84             }
85             }
86              
87             event delay_notification => sub {
88             my ( $kernel, $self, $until, $pool, $request, $value ) = @_[KERNEL, OBJECT, ARG0 .. $#_];
89              
90             $self->_requests->{$request} = $kernel->delay_set( request_may_be_free => $until, $pool, $request, $value );
91             };
92              
93             event request_may_be_free => sub {
94             my ( $kernel, $self, $pool, $request, $value ) = @_[KERNEL, OBJECT, ARG0 .. $#_];
95              
96             if ( my $until = $self->token_bucket->until($value) ) {
97             $self->_requests->{$request} = $kernel->delay_set( request_may_be_free => $until, $pool, $request, $value );
98             } else {
99             delete $self->_requests->{$request};
100             $request->pool->resource_updated( $self, $request );
101             }
102             };
103              
104             __PACKAGE__
105              
106             __END__
107              
108             =pod
109              
110             =head1 NAME
111              
112             POE::Component::ResourcePool::Resource::TokenBucket - Token bucket based
113             resource (for throttling).
114              
115             =head1 SYNOPSIS
116              
117             use POE::Component::ResourcePool::Resource::TokenBucket;
118              
119             my $tb = POE::Component::ResourcePool::Resource::TokenBucket->new(
120             # see Algorithm::TokenBucket
121             rate => $per_second,
122             burst => $max_item_size,
123             );
124              
125             my $pool = POE::Component::ResourcePool->new(
126             resources => {
127             rate_limit => $tb,
128             },
129             );
130              
131             # requests can ask the rate_limit resource to throttle them now
132              
133             =head1 DESCRIPTIONS
134              
135             This class implements an L<Algorithm::TokenBucket> based resource for
136             L<POE::Component::ResourcePool>.
137              
138             Requests are numeric value based, and will be served as the token bucket fills.
139              
140             This is useful for rate limiting of jobs in a time based way.
141              
142             =head1 ATTRIBUTES
143              
144             =over 4
145              
146             =item alias
147              
148             The POE alias for the internal session.
149              
150             Comes from L<MooseX::POE::Aliased>.
151              
152             The alias can be set explicitly but is not yet useful for anything (there is no
153             POE side API for this object, all session states are internal).
154              
155             =item token_bucket
156              
157             The L<Algorithm::TokenBucket> object used to calculate the rate limiting.
158              
159             This is readonly.
160              
161             =item rate
162              
163             =item burst
164              
165             The numerical parameters for L<Algorithm::TokenBucket> used to generate
166             C<token_bucket>.
167              
168             These are also used for C<could_allocate>, etc.
169              
170             =back
171              
172             =head1 METHODS
173              
174             See L<POE::Component::ResourcePool::Resource> for the resource API.
175              
176             =head1 SEE ALSO
177              
178             L<POE>, L<MooseX::POE>, L<Algorithm::TokenBucket>,
179             L<POE::Component::ResourcePool>.
180              
181             =head1 VERSION CONTROL
182              
183             This module is maintained using Darcs. You can get the latest version from
184             L<http://nothingmuch.woobling.org/code>, and use C<darcs send> to commit
185             changes.
186              
187             =head1 AUTHOR
188              
189             Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt>
190              
191             =head1 COPYRIGHT
192              
193             Copyright (c) 2008 Yuval Kogman. All rights reserved
194             This program is free software; you can redistribute
195             it and/or modify it under the same terms as Perl itself.
196              
197             =cut