File Coverage

blib/lib/MetaCPAN/Client/Scroll.pm
Criterion Covered Total %
statement 48 51 94.1
branch 8 14 57.1
condition 4 7 57.1
subroutine 11 11 100.0
pod 3 3 100.0
total 74 86 86.0


line stmt bran cond sub pod time code
1 21     21   108552 use strict;
  21         53  
  21         535  
2 21     21   90 use warnings;
  21         46  
  21         931  
3             package MetaCPAN::Client::Scroll;
4             # ABSTRACT: A MetaCPAN::Client scroller
5             $MetaCPAN::Client::Scroll::VERSION = '2.030000';
6 21     21   575 use Moo;
  21         10117  
  21         180  
7 21     21   6611 use Carp;
  21         44  
  21         1120  
8 21     21   120 use Ref::Util qw< is_hashref >;
  21         53  
  21         864  
9 21     21   871 use JSON::MaybeXS qw< decode_json encode_json >;
  21         11840  
  21         1026  
10              
11 21     21   6802 use MetaCPAN::Client::Types qw< Str Int Time ArrayRef HashRef Bool >;
  21         54  
  21         13842  
12              
13             has ua => (
14             is => 'ro',
15             required => 1,
16             );
17              
18             has size => (
19             is => 'ro',
20             isa => Str,
21             );
22              
23             has time => (
24             is => 'ro',
25             isa => Time,
26             );
27              
28             has base_url => (
29             is => 'ro',
30             isa => Str,
31             required => 1,
32             );
33              
34             has type => (
35             is => 'ro',
36             isa => Str,
37             required => 1,
38             );
39              
40             has body => (
41             is => 'ro',
42             isa => HashRef,
43             required => 1,
44             );
45              
46             has _id => (
47             is => 'ro',
48             isa => Str,
49             );
50              
51             has _buffer => (
52             is => 'ro',
53             isa => ArrayRef,
54             default => sub { [] },
55             );
56              
57             has _done => (
58             is => 'rw',
59             isa => Bool,
60             default => sub { 0 },
61             );
62              
63             has total => (
64             is => 'ro',
65             isa => Int,
66             );
67              
68             has aggregations => (
69             is => 'ro',
70             isa => HashRef,
71             default => sub { +{} },
72             );
73              
74             sub BUILDARGS {
75 11     11 1 47747 my ( $class, %args ) = @_;
76 11   100     59 $args{time} //= '5m';
77 11   50     50 $args{size} //= '100';
78              
79             my ( $ua, $base_url, $type, $body, $time, $size ) =
80 11         62 @args{qw< ua base_url type body time size >};
81              
82             # fetch scroller from server
83              
84 11         448 my $res = $ua->post(
85             sprintf( '%s/%s/_search?scroll=%s&size=%s', $base_url, $type, $time, $size ),
86             { content => encode_json $body }
87             );
88              
89 11 50       3260452 if ( $res->{status} != 200 ) {
90 0         0 my $msg = "failed to create a scrolled search";
91 0 0       0 $args{debug} and $msg .= "\n(" . $res->{content} . ")";
92 0         0 croak $msg;
93             }
94              
95 11         111658 my $content = decode_json $res->{content};
96              
97             # read response content --> object params
98              
99 11         89 $args{_id} = $content->{_scroll_id};
100 11         53 $args{total} = $content->{hits}{total};
101 11         40 $args{_buffer} = $content->{hits}{hits};
102              
103             $args{aggregations} = $content->{aggregations}
104 11 50 33     74 if $content->{aggregations} and is_hashref( $content->{aggregations} );
105              
106 11         1413 return \%args;
107             }
108              
109             sub next {
110 112     112 1 3463 my $self = shift;
111 112         168 my $buffer = $self->_buffer;
112              
113             # We're exhausted and will do no more.
114 112 50       1776 return if $self->_done;
115              
116             # Refill the buffer if it's empty.
117 112 100       683 @$buffer = @{ $self->_fetch_next }
  4         26  
118             unless @$buffer;
119              
120             # Grab the next result from the buffer. If there's no result, then that's
121             # all, folks!
122 112         167 my $next = shift @$buffer;
123              
124 112 100       302 $self->_done(1) unless $next;
125              
126 112         312 return $next;
127             }
128              
129             sub _fetch_next {
130 4     4   11 my $self = shift;
131              
132 4         113 my $res = $self->ua->post(
133             sprintf( '%s/_search/scroll?scroll=%s&size=%s', $self->base_url, $self->time, $self->size ),
134             { content => $self->_id }
135             );
136              
137             croak "failed to fetch next scrolled batch"
138 4 50       321958 unless $res->{status} == 200;
139              
140 4         4299 my $content = decode_json $res->{content};
141              
142 4         46 return $content->{hits}{hits};
143             }
144              
145             sub DEMOLISH {
146 11     11 1 19362 my $self = shift;
147              
148 11         345 $self->ua->delete(
149             sprintf( '%s/_search/scroll?scroll=%s', $self->base_url, $self->time ),
150             { content => $self->_id }
151             );
152             }
153              
154             1;
155              
156             __END__