line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package AnyEvent::HTTP::MultiGet; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
961
|
use Modern::Perl; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
22
|
|
4
|
3
|
|
|
3
|
|
1199
|
use Moo; |
|
3
|
|
|
|
|
3736
|
|
|
3
|
|
|
|
|
17
|
|
5
|
3
|
|
|
3
|
|
2483
|
use MooX::Types::MooseLike::Base qw(:all); |
|
3
|
|
|
|
|
7880
|
|
|
3
|
|
|
|
|
1034
|
|
6
|
3
|
|
|
3
|
|
29
|
use Data::Dumper; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
193
|
|
7
|
3
|
|
|
3
|
|
25
|
use Ref::Util qw(is_plain_arrayref); |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
170
|
|
8
|
3
|
|
|
3
|
|
29
|
use namespace::clean; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
34
|
|
9
|
|
|
|
|
|
|
Log::Log4perl->wrapper_register(__PACKAGE__); |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
BEGIN { |
12
|
3
|
|
|
3
|
|
2660
|
extends 'HTTP::MultiGet'; |
13
|
|
|
|
|
|
|
} |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $VERSION=$HTTP::MultiGet::VERSION; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 NAME |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
AnyEvent::HTTP::MultiGet - AnyEvent->condvar Control Freindly LWP Like agent |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use Modern::Perl; |
24
|
|
|
|
|
|
|
use AnyEvent::HTTP::MultiGet; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
my $self=AnyEvent::HTTP::MultiGet->new(); |
27
|
|
|
|
|
|
|
my $count=0; |
28
|
|
|
|
|
|
|
TEST_LOOP: { |
29
|
|
|
|
|
|
|
my $req=HTTP::Request->new(GET=>'http://google.com'); |
30
|
|
|
|
|
|
|
my $req_b=HTTP::Request->new(GET=>'https://127.0.0.1:5888'); |
31
|
|
|
|
|
|
|
my @todo=HTTP::Request->new(GET=>'http://yahoo.com'); |
32
|
|
|
|
|
|
|
push @todo,HTTP::Request->new(GET=>'http://news.com'); |
33
|
|
|
|
|
|
|
push @todo,HTTP::Request->new(GET=>'https://news.com'); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
my $total=2 + scalar(@todo); |
36
|
|
|
|
|
|
|
my $cv=AnyEvent->condvar; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my $code; |
39
|
|
|
|
|
|
|
$code=sub { |
40
|
|
|
|
|
|
|
my ($obj,$request,$result)=@_; |
41
|
|
|
|
|
|
|
printf 'HTTP Response code: %i'."\n",$result->code; |
42
|
|
|
|
|
|
|
++$count; |
43
|
|
|
|
|
|
|
if(my $next=shift @todo) { |
44
|
|
|
|
|
|
|
$self->add_cb($req,$code); |
45
|
|
|
|
|
|
|
$self->run_next; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
no warnings; |
48
|
|
|
|
|
|
|
$cv->send if $total==$count; |
49
|
|
|
|
|
|
|
}; |
50
|
|
|
|
|
|
|
$self->add_cb($req,$code); |
51
|
|
|
|
|
|
|
$self->add_cb($req_b,$code); |
52
|
|
|
|
|
|
|
$self->run_next; |
53
|
|
|
|
|
|
|
$cv->recv; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
Handling Multiple large http requests at once |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
use Modern::Perl; |
59
|
|
|
|
|
|
|
use AnyEvent::HTTP::MultiGet; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
my $self=AnyEvent::HTTP::MultiGet->new(); |
62
|
|
|
|
|
|
|
my $chunks=0; |
63
|
|
|
|
|
|
|
my $count=0; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
my $req=HTTP::Request->new(GET=>'https://google.com'); |
67
|
|
|
|
|
|
|
my $req_b=HTTP::Request->new(GET=>'https://yahoo.com'); |
68
|
|
|
|
|
|
|
my $req_c=HTTP::Request->new(GET=>'https://news.com'); |
69
|
|
|
|
|
|
|
$total=3; |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
my @todo; |
72
|
|
|
|
|
|
|
push @todo,HTTP::Request->new(GET=>'https://127.0.0.1:5888'); |
73
|
|
|
|
|
|
|
push @todo,HTTP::Request->new(GET=>'https://127.0.0.1:5887'); |
74
|
|
|
|
|
|
|
push @todo,HTTP::Request->new(GET=>'https://127.0.0.1:5886'); |
75
|
|
|
|
|
|
|
push @todo,HTTP::Request->new(GET=>'https://127.0.0.1:5885'); |
76
|
|
|
|
|
|
|
$total +=scalar(@todo); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
TEST_LOOP: { |
79
|
|
|
|
|
|
|
my $on_body=sub { |
80
|
|
|
|
|
|
|
my ($getter,$request,$headers,$chunk)=@_; |
81
|
|
|
|
|
|
|
# 0: Our AnyEvent::HTTP::MultiGet instance |
82
|
|
|
|
|
|
|
# 1: the HTTP::Request object |
83
|
|
|
|
|
|
|
# 2: An HTTP::Headers object representing the current headers |
84
|
|
|
|
|
|
|
# 3: Current Data Chunk |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
++$chunks; |
87
|
|
|
|
|
|
|
printf 'request is %s'."\n",$request->uri; |
88
|
|
|
|
|
|
|
printf 'status code was: %i'."\n",$headers->header('Status'); |
89
|
|
|
|
|
|
|
printf 'content length was: %i'."\n",length($body); |
90
|
|
|
|
|
|
|
}; |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
my $code; |
93
|
|
|
|
|
|
|
my $cb=AnyEvent->condvar; |
94
|
|
|
|
|
|
|
$code=sub { |
95
|
|
|
|
|
|
|
my ($obj,$request,$result)=@_; |
96
|
|
|
|
|
|
|
printf 'HTTP Response code: %i %s'."\n",$result->code,$request->url; |
97
|
|
|
|
|
|
|
++$count; |
98
|
|
|
|
|
|
|
print "We are at response $count\n"; |
99
|
|
|
|
|
|
|
if(my $next=shift @todo) { |
100
|
|
|
|
|
|
|
$self->add_cb([$next,on_body=>$on_body],$code); |
101
|
|
|
|
|
|
|
$self->run_next; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
no warnings; |
104
|
|
|
|
|
|
|
$cv->send if $count==$total; |
105
|
|
|
|
|
|
|
}; |
106
|
|
|
|
|
|
|
$self->add_cb([$req,on_body=>$on_body],$code); |
107
|
|
|
|
|
|
|
$self->add_cb([$req_b,on_body=>$on_body],$code); |
108
|
|
|
|
|
|
|
$self->add_cb([$req_c,on_body=>$on_body],$code); |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
$self->run_next; |
111
|
|
|
|
|
|
|
$cv->recv; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 DESCRIPTION |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
This class provides an AnyEvent->condvar frienddly implementation of HTTP::MultiGet. |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=head1 OO Arguments and accessors |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
Arguemnts and object accessors: |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
logger: DOES(Log::Log4perl::Logger) |
125
|
|
|
|
|
|
|
request_opts: See AnyEvent::HTTP params for details |
126
|
|
|
|
|
|
|
timeout: Global timeout for everything |
127
|
|
|
|
|
|
|
max_que_count: How many requests to run at once |
128
|
|
|
|
|
|
|
max_retry: How many times to retry if we get a connection/negotiation error |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
For internal use only: |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
in_control_loop: true when in the control loop |
133
|
|
|
|
|
|
|
stack: Data::Queue object |
134
|
|
|
|
|
|
|
que_count: Total Number of elements active in the que |
135
|
|
|
|
|
|
|
retry: Anonymous hash used to map ids to retry counts |
136
|
|
|
|
|
|
|
cb_map: Anonymous hash used to map ids to callbacks |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=cut |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
has cb_map=>( |
141
|
|
|
|
|
|
|
is=>'ro', |
142
|
|
|
|
|
|
|
isa=>HashRef, |
143
|
|
|
|
|
|
|
default=>sub { {} }, |
144
|
|
|
|
|
|
|
required=>1, |
145
|
|
|
|
|
|
|
); |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
# This method runs after the new constructor |
148
|
|
|
|
|
|
|
sub BUILD { |
149
|
3
|
|
|
3
|
0
|
54
|
my ($self)=@_; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# this method runs before the new constructor, and can be used to change the arguments passed to the module |
153
|
|
|
|
|
|
|
around BUILDARGS => sub { |
154
|
|
|
|
|
|
|
my ($org,$class,@args)=@_; |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
return $class->$org(@args); |
157
|
|
|
|
|
|
|
}; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=head1 OO Methods |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=over 4 |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=item * my $id=$self->add_cb($request,$code) |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Adds a request with a callback handler. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=item * my $id=$self->add_cb([$request,key=>value],$code); |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
Wrapping [$request] allows passing additional key value to L<AnyEvent::HTTP::Request>, with one exception, on_body=>$code is wrapped an additional callback. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=cut |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub add_cb { |
174
|
2
|
|
|
2
|
1
|
6
|
my ($self,$request,$code)=@_; |
175
|
2
|
|
|
|
|
14
|
my ($id)=$self->add($request); |
176
|
2
|
50
|
|
|
|
7
|
my $req=is_plain_arrayref($request) ? $request->[0] : $request; |
177
|
2
|
|
|
|
|
10
|
$self->cb_map->{$id}=[$code,$req]; |
178
|
2
|
|
|
|
|
9
|
return $id; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub que_function { |
182
|
2
|
|
|
2
|
1
|
6
|
my ($self,$req,$id)=@_; |
183
|
2
|
|
|
|
|
9
|
my $code=$self->SUPER::que_function($req,$id); |
184
|
|
|
|
|
|
|
|
185
|
2
|
|
|
|
|
4
|
my $cb; |
186
|
|
|
|
|
|
|
$cb=sub { |
187
|
2
|
|
|
2
|
|
490
|
$code->(@_); |
188
|
2
|
|
|
|
|
7
|
$self->_common_handle_callback($id); |
189
|
2
|
|
|
|
|
7
|
$self->run_next; |
190
|
2
|
|
|
|
|
222
|
$self->log_always("our que count is: ".$self->que_count); |
191
|
2
|
|
|
|
|
90
|
undef $cb; |
192
|
2
|
|
|
|
|
20
|
}; |
193
|
2
|
|
|
|
|
7
|
return $cb; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub _common_handle_callback { |
197
|
8
|
|
|
8
|
|
19
|
my ($self,$id)=@_; |
198
|
8
|
100
|
|
|
|
34
|
if(exists $self->cb_map->{$id}) { |
199
|
2
|
50
|
|
|
|
47
|
if(exists $self->results->{$id}) { |
200
|
2
|
|
|
|
|
19
|
my ($code,$req)=@{delete $self->cb_map->{$id}}; |
|
2
|
|
|
|
|
19
|
|
201
|
2
|
|
|
|
|
43
|
my $result=delete $self->results->{$id}; |
202
|
2
|
|
|
|
|
17
|
my $response; |
203
|
2
|
50
|
|
|
|
5
|
if($result) { |
204
|
2
|
|
|
|
|
97
|
$response=$result->get_data; |
205
|
|
|
|
|
|
|
} else { |
206
|
0
|
|
|
|
|
0
|
$response=$self->RESPONSE_CLASS->new('',{Status=>500,Reason=>"Request Timed out"})->to_http_message; |
207
|
|
|
|
|
|
|
} |
208
|
2
|
|
|
|
|
13
|
$code->($self,$req,$response); |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
} else { |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub block_for_ids { |
215
|
6
|
|
|
6
|
1
|
17
|
my ($self,@ids)=@_; |
216
|
6
|
|
|
|
|
25
|
my $result=$self->SUPER::block_for_ids(@ids); |
217
|
|
|
|
|
|
|
|
218
|
6
|
100
|
|
|
|
1668
|
if($result) { |
219
|
2
|
|
|
|
|
100
|
foreach my $id (@ids) { |
220
|
2
|
|
|
|
|
7
|
$self->results->{$id}=$result->get_data->{$id}; |
221
|
2
|
|
|
|
|
55
|
$self->_common_handle_callback($id); |
222
|
2
|
|
|
|
|
82
|
delete $self->results->{$id}; |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
} else { |
225
|
4
|
|
|
|
|
188
|
foreach my $id (@ids) { |
226
|
4
|
|
|
|
|
12
|
$self->results->{$id}=$self->new_false("$result"); |
227
|
4
|
|
|
|
|
983
|
$self->_common_handle_callback($id); |
228
|
4
|
|
|
|
|
66
|
delete $self->results->{$id}; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
6
|
|
|
|
|
449
|
return $result; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=back |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=head1 AUTHOR |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
Michael Shipper <AKALINUX@CPAN.ORG> |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=cut |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
1; |