File Coverage

blib/lib/Connector/Tee.pm
Criterion Covered Total %
statement 64 70 91.4
branch 11 14 78.5
condition 4 5 80.0
subroutine 9 9 100.0
pod 3 3 100.0
total 91 101 90.1


line stmt bran cond sub pod time code
1              
2             use strict;
3 1     1   6 use warnings;
  1         2  
  1         25  
4 1     1   4 use English;
  1         1  
  1         22  
5 1     1   4 use Moose;
  1         1  
  1         4  
6 1     1   277 use Data::Dumper;
  1         2  
  1         5  
7 1     1   5245  
  1         2  
  1         579  
8             extends 'Connector::Proxy';
9              
10             # Location must not be used
11             has '+LOCATION' => ( required => 0, 'isa' => 'Undef' );
12              
13             has branches => (
14             is => 'rw',
15             isa => 'ArrayRef',
16             );
17              
18             has accept => (
19             is => 'rw',
20             isa => 'Str',
21             default => '',
22             );
23              
24              
25             my $self = shift;
26             my $location = shift;
27 4     4 1 5 my @args = @_;
28 4         6  
29 4         6 my $accept = $self->accept();
30             $self->log()->trace('initialize tee');
31 4         80  
32 4         68 foreach my $child ( @{$self->branches()} ) {
33              
34 4         20 $self->log()->debug('query child ' . $child );
  4         78  
35              
36 8         155 my @prefix = $self->conn()->_build_path([ 'nodes', $child, @{$location}] );
37              
38 8         210 my $result = $self->conn()->get( \@prefix , \@args );
  8         22  
39              
40 8         202 $self->log()->trace('raw result ' . ($result // 'undef'));
41              
42 8   100     152 if (!defined $result) {
43             } elsif (!$accept) {
44 8 100       118 return $result;
    100          
    100          
45             } elsif ($result =~ qr/$accept/) {
46 2         15 $self->log()->debug('result accepted (scalar)');
47             return $result;
48 2         36 } else {
49 2         26 $self->log()->debug('result mismatches pattern (scalar)');
50             $self->log()->trace($accept . ' - ' . $result);
51 3         59 }
52 3         65 }
53              
54             return $self->_node_not_exists( $location );
55              
56 0         0 }
57              
58              
59             my $self = shift;
60             my $location = shift;
61             my @args = @_;
62 1     1 1 2  
63 1         2 my $accept = $self->accept();
64 1         2 $self->log()->trace('initialize tee');
65              
66 1         22 foreach my $child ( @{$self->branches()} ) {
67 1         18  
68             $self->log()->debug('query child ' . $child );
69 1         6  
  1         20  
70             my @prefix = $self->conn()->_build_path([ 'nodes', $child, @{$location}] );
71 2         40  
72             my $result = $self->conn()->get_hash( \@prefix , \@args );
73 2         54  
  2         7  
74             $self->log()->trace('raw result ' . ($result // Dumper $result));
75 2         52  
76             if (!defined $result) {
77 2   66     45  
78             } elsif (!$accept) {
79 2 100       53 return $result;
    50          
    0          
80             } elsif (keys %{$result}) {
81             $self->log()->debug('result accepted (hash)');
82 1         6 return $result;
83 0         0 }
84 0         0 }
85 0         0  
86             return $self->_node_not_exists( $location );
87             }
88              
89 0         0  
90              
91             my $self = shift;
92             my $location = shift;
93             my @args = @_;
94              
95 1     1 1 2 $self->log()->trace('initialize tee');
96 1         2  
97 1         2 foreach my $child ( @{$self->branches()} ) {
98              
99 1         19 $self->log()->debug('query child ' . $child );
100              
101 1         6 my @prefix = $self->conn()->_build_path([ 'nodes', $child, @{$location}] );
  1         21  
102              
103 2         37 my @result = $self->conn()->get_list( \@prefix , \@args );
104              
105 2         53 $self->log()->trace('raw result ' . (Dumper \@result));
  2         7  
106              
107 2         51 if (@result) {
108             $self->log()->debug('result accepted (list)');
109 2         39 return @result;
110             }
111 2 100       102 }
112 1         23  
113 1         13 return $self->_node_not_exists( $location );
114              
115             }
116              
117 0            
118             no Moose;
119             __PACKAGE__->meta->make_immutable;
120              
121             1;
122 1     1   7  
  1         2  
  1         4  
123             =head1 Name
124              
125             Connector::Tee
126              
127             =head1 Description
128              
129             This connector can be used to search for a value over multiple branches
130             in a way that is transparent to the caller.
131              
132             =head1 Configurarion Example
133              
134             class: Connector::Tee
135             accept: "\\A[a-zA-Z]+\\z"
136             branches:
137             - static
138             - conn1
139             - conn2
140              
141             nodes:
142             static:
143             test1: NO
144             test2: YES
145             test3: 0
146             conn1@: connector:connectors.conn1
147             conn2@: connector:connectors.conn2
148              
149             If the connector with the above configuration is called with I<get('test1')>,
150             the request is dispatched to nodes.static.test1 which evaluates to I<NO>
151             and is returned as the overall result.
152              
153             If you call I<get('test3')>, the result is NOT I<0> as this does not match
154             the regex given as accept pattern! The request is therefore resend to
155             nodes.conn1.test3 which is revolved to another connector call. In case
156             the result of this connector does also not match the pattern (or is empty),
157             the same request is send to nodes.conn2.test3.
158              
159             For the scalar I<get> call, the value given to accept is evaluated as a
160             case-sensitive regex pattern using qr// internally. If you set accept to
161             the empty string, any defined value is accepted.
162              
163             For I<get_hash>, an empty value for accept will let the empty hash pass,
164             if accept is set to any true value, only non-empty hashes are accepted.
165              
166             For I<get_list>, accept is ignored and only non-empty lists are accepted.
167