File Coverage

blib/lib/Elasticsearch/CxnPool/Sniff.pm
Criterion Covered Total %
statement 36 36 100.0
branch 12 12 100.0
condition n/a
subroutine 6 6 100.0
pod 2 3 66.6
total 56 57 98.2


line stmt bran cond sub pod time code
1             package Elasticsearch::CxnPool::Sniff;
2             $Elasticsearch::CxnPool::Sniff::VERSION = '1.05';
3 10     10   8353 use Moo;
  10         23  
  10         75  
4             with 'Elasticsearch::Role::CxnPool::Sniff', 'Elasticsearch::Role::Is_Sync';
5              
6 10     10   4508 use Elasticsearch::Util qw(throw);
  10         37  
  10         91  
7 10     10   3358 use namespace::clean;
  10         25  
  10         90  
8              
9             #===================================
10             sub next_cxn {
11             #===================================
12 51     51 1 122 my ($self) = @_;
13              
14 51 100       454 $self->sniff if $self->next_sniff <= time();
15              
16 51         675 my $cxns = $self->cxns;
17 51         97 my $total = @$cxns;
18              
19 51         188 while ( 0 < $total-- ) {
20 49         198 my $cxn = $cxns->[ $self->next_cxn_num ];
21 49 100       407 return $cxn if $cxn->is_live;
22             }
23              
24 6         38 throw( "NoNodes",
25             "No nodes are available: [" . $self->cxns_seeds_str . ']' );
26             }
27              
28             #===================================
29             sub sniff {
30             #===================================
31 30     30 1 63 my $self = shift;
32              
33 30         110 my $cxns = $self->cxns;
34 30         68 my $total = @$cxns;
35 30         50 my @skipped;
36              
37 30         120 while ( 0 < $total-- ) {
38 19         204 my $cxn = $cxns->[ $self->next_cxn_num ];
39 19 100       102 if ( $cxn->is_dead ) {
40 5         19 push @skipped, $cxn;
41             }
42             else {
43 14 100       55 $self->sniff_cxn($cxn) and return;
44 1         12 $cxn->mark_dead;
45             }
46             }
47              
48 17         53 for my $cxn (@skipped) {
49 4 100       11 $self->sniff_cxn($cxn) and return;
50             }
51              
52 16         151 $self->logger->infof("No live nodes available. Trying seed nodes.");
53 16         1373 for my $seed ( @{ $self->seed_nodes } ) {
  16         99  
54 21         184 my $cxn = $self->cxn_factory->new_cxn($seed);
55 21 100       9118 $self->sniff_cxn($cxn) and return;
56             }
57              
58             }
59              
60             #===================================
61             sub sniff_cxn {
62             #===================================
63 39     39 0 90 my ( $self, $cxn ) = @_;
64 39         191 return $self->parse_sniff( $cxn->protocol, $cxn->sniff );
65             }
66              
67             1;
68              
69             # ABSTRACT: A CxnPool for connecting to a local cluster with a dynamic node list
70              
71             __END__
72              
73             =pod
74              
75             =encoding UTF-8
76              
77             =head1 NAME
78              
79             Elasticsearch::CxnPool::Sniff - A CxnPool for connecting to a local cluster with a dynamic node list
80              
81             =head1 VERSION
82              
83             version 1.05
84              
85             =head1 SYNOPSIS
86              
87             $e = Elasticsearch->new(
88             cxn_pool => 'Sniff',
89             nodes => [
90             'search1:9200',
91             'search2:9200'
92             ],
93             );
94              
95             =head1 DESCRIPTION
96              
97             The L<Sniff|Elasticsearch::CxnPool::Sniff> connection pool should be used
98             when you B<do> have direct access to the Elasticsearch cluster, eg when
99             your web servers and Elasticsearch servers are on the same network.
100             The nodes that you specify are used to I<discover> the cluster, which is
101             then I<sniffed> to find the current list of live nodes that the cluster
102             knows about.
103              
104             This sniff process is repeated regularly, or whenever a node fails,
105             to update the list of healthy nodes. So if you add more nodes to your
106             cluster, they will be auto-discovered during a sniff.
107              
108             If all sniffed nodes fail, then it falls back to sniffing the original
109             I<seed> nodes that you specified in C<new()>.
110              
111             For L<HTTP Cxn classes|Elasticsearch::Role::Cxn::HTTP>, this module
112             will also dynamically detect the C<max_content_length> which the nodes
113             in the cluster will accept.
114              
115             This class does L<Elasticsearch::Role::CxnPool::Sniff> and
116             L<Elasticsearch::Role::Is_Sync>.
117              
118             =head1 CONFIGURATION
119              
120             =head2 C<nodes>
121              
122             The list of nodes to use to discover the cluster. Can accept a single node,
123             multiple nodes, and defaults to C<localhost:9200> if no C<nodes> are
124             specified. See L<Elasticsearch::Role::Cxn::HTTP/node> for details of the node
125             specification.
126              
127             =head2 See also
128              
129             =over
130              
131             =item *
132              
133             L<Elasticsearch::Role::Cxn/request_timeout>
134              
135             =item *
136              
137             L<Elasticsearch::Role::Cxn/sniff_timeout>
138              
139             =item *
140              
141             L<Elasticsearch::Role::Cxn/sniff_request_timeout>
142              
143             =back
144              
145             =head2 Inherited configuration
146              
147             From L<Elasticsearch::Role::CxnPool::Sniff>
148              
149             =over
150              
151             =item * L<sniff_interval|Elasticsearch::Role::CxnPool::Sniff/"sniff_interval">
152              
153             =item * L<sniff_max_content_length|Elasticsearch::Role::CxnPool::Sniff/"sniff_max_content_length">
154              
155             =back
156              
157             From L<Elasticsearch::Role::CxnPool>
158              
159             =over
160              
161             =item * L<randomize_cxns|Elasticsearch::Role::CxnPool/"randomize_cxns">
162              
163             =back
164              
165             =head1 METHODS
166              
167             =head2 C<next_cxn()>
168              
169             $cxn = $cxn_pool->next_cxn
170              
171             Returns the next available live node (in round robin fashion), or
172             throws a C<NoNodes> error if no nodes can be sniffed from the cluster.
173              
174             =head2 C<schedule_check()>
175              
176             $cxn_pool->schedule_check
177              
178             Forces a sniff before the next Cxn is returned, to updated the list of healthy
179             nodes in the cluster.
180              
181             =head2 C<sniff()>
182              
183             $bool = $cxn_pool->sniff
184              
185             Sniffs the cluster and returns C<true> if the sniff was successful.
186              
187             =head2 Inherited methods
188              
189             From L<Elasticsearch::Role::CxnPool::Sniff>
190              
191             =over
192              
193             =item * L<schedule_check()|Elasticsearch::Role::CxnPool::Sniff/"schedule_check()">
194              
195             =item * L<parse_sniff()|Elasticsearch::Role::CxnPool::Sniff/"parse_sniff()">
196              
197             =item * L<should_accept_node()|Elasticsearch::Role::CxnPool::Sniff/"should_accept_node()">
198              
199             =back
200              
201             From L<Elasticsearch::Role::CxnPool>
202              
203             =item * L<cxn_factory()|Elasticsearch::Role::CxnPool/"cxn_factory()">
204              
205             =item * L<logger()|Elasticsearch::Role::CxnPool/"logger()">
206              
207             =item * L<serializer()|Elasticsearch::Role::CxnPool/"serializer()">
208              
209             =item * L<current_cxn_num()|Elasticsearch::Role::CxnPool/"current_cxn_num()">
210              
211             =item * L<cxns()|Elasticsearch::Role::CxnPool/"cxns()">
212              
213             =item * L<seed_nodes()|Elasticsearch::Role::CxnPool/"seed_nodes()">
214              
215             =item * L<next_cxn_num()|Elasticsearch::Role::CxnPool/"next_cxn_num()">
216              
217             =item * L<set_cxns()|Elasticsearch::Role::CxnPool/"set_cxns()">
218              
219             =item * L<request_ok()|Elasticsearch::Role::CxnPool/"request_ok()">
220              
221             =item * L<request_failed()|Elasticsearch::Role::CxnPool/"request_failed()">
222              
223             =item * L<should_retry()|Elasticsearch::Role::CxnPool/"should_retry()">
224              
225             =item * L<should_mark_dead()|Elasticsearch::Role::CxnPool/"should_mark_dead()">
226              
227             =item * L<cxns_str()|Elasticsearch::Role::CxnPool/"cxns_str()">
228              
229             =item * L<cxns_seeds_str()|Elasticsearch::Role::CxnPool/"cxns_seeds_str()">
230              
231             =item * L<retries()|Elasticsearch::Role::CxnPool/"retries()">
232              
233             =item * L<reset_retries()|Elasticsearch::Role::CxnPool/"reset_retries()">
234              
235             =back
236              
237             =head1 AUTHOR
238              
239             Clinton Gormley <drtech@cpan.org>
240              
241             =head1 COPYRIGHT AND LICENSE
242              
243             This software is Copyright (c) 2014 by Elasticsearch BV.
244              
245             This is free software, licensed under:
246              
247             The Apache License, Version 2.0, January 2004
248              
249             =cut