File Coverage

blib/lib/PawsX/Waiter/Client.pm
Criterion Covered Total %
statement 23 82 28.0
branch 0 30 0.0
condition 0 18 0.0
subroutine 8 18 44.4
pod 0 8 0.0
total 31 156 19.8


line stmt bran cond sub pod time code
1             package PawsX::Waiter::Client;
2              
3 2     2   28 use v5.20;
  2         7  
4 2     2   11 use Moose;
  2         4  
  2         20  
5              
6 2     2   15568 use feature qw(postderef say);
  2         5  
  2         330  
7 2     2   15 no warnings qw(experimental::postderef);
  2         4  
  2         91  
8              
9 2     2   924 use Jmespath;
  2         525118  
  2         74  
10 2     2   987 use Data::Structure::Util qw(unbless);
  2         14244  
  2         137  
11 2     2   15 use Try::Tiny;
  2         5  
  2         131  
12              
13 2     2   966 use PawsX::Waiter::Exception;
  2         8  
  2         2622  
14              
15             has client => (
16             is => 'ro',
17             required => 1,
18             weak_ref => 1,
19             );
20              
21             has delay => (
22             is => 'rw',
23             isa => 'Int',
24             required => 1,
25             );
26              
27             has maxAttempts => (
28             is => 'rw',
29             isa => 'Int',
30             required => 1,
31             );
32              
33             has operation => (
34             is => 'ro',
35             isa => 'Str',
36             required => 1,
37             );
38              
39             has acceptors => (
40             is => 'ro',
41             isa => 'ArrayRef[HashRef]',
42             required => 1,
43             );
44              
45             has 'beforeWait' => (
46             traits => ['Code'],
47             is => 'rw',
48             isa => 'CodeRef',
49             predicate => 'has_beforeWait',
50             handles => {
51             _beforeWait => 'execute_method',
52             },
53             );
54              
55             sub operation_request {
56 0     0 0   my ( $self, $options ) = @_;
57              
58 0           my $func = $self->operation;
59 0           my $response = {};
60              
61             try {
62 0     0     $response = $self->client->$func( $options->%* );
63             }
64             catch {
65 0     0     my $error = $_;
66 0 0 0       if ( blessed($error) and $error->isa('Paws::Exception') ) {
67 0           $response = {
68             code => $error->code,
69             request_id => $error->request_id,
70             http_status => $error->http_status,
71             message => $error->message,
72             };
73             }
74             else {
75 0           PawsX::Waiter::Exception->throw(
76             name => $self->operation,
77             reason => $error,
78             last_response => $response,
79             );
80             }
81 0           };
82 0 0         return blessed($response) ? unbless($response) : $response;
83             }
84              
85             sub wait {
86 0     0 0   my ( $self, $options ) = @_;
87              
88 0           my $current_state = 'waiting';
89 0           my $num_attempts = 0;
90              
91 0           while (1) {
92            
93 0           my $response = $self->operation_request($options);
94 0           $num_attempts++;
95            
96             ACCEPTOR:
97 0           foreach my $acceptor ( $self->acceptors->@* ) {
98 0 0         if ( my $status = $self->matcher( $acceptor, $response ) ) {
99 0           $current_state = $acceptor->{'state'};
100 0           last ACCEPTOR;
101             }
102             }
103              
104 0 0         if ( $current_state eq 'success' ) { return; }
  0            
105 0 0         if ( $current_state eq 'failure' ) {
106 0           PawsX::Waiter::Exception->throw(
107             message => 'Waiter encountered a terminal failure state',
108             last_response => $response,
109             );
110             }
111 0 0         if ( $num_attempts >= $self->maxAttempts ) {
112 0           PawsX::Waiter::Exception::TimeOut->throw(
113             message => 'Max attempts exceeded',
114             last_response => $response,
115             );
116             }
117              
118 0 0         $self->_beforeWait($num_attempts, $response) if $self->has_beforeWait;
119              
120 0           sleep( $self->delay );
121             }
122             }
123              
124             sub matcher {
125 0     0 0   my ( $self, $acceptor, $response ) = @_;
126              
127 0           my $func = "match_" . $acceptor->{'matcher'};
128              
129 0           return $self->$func( $acceptor, $response );
130             }
131              
132             sub match_path {
133 0     0 0   my ( $self, $acceptor, $response ) = @_;
134              
135 0 0         if ( 'HASH' eq ref $response ) {
136             my $ret =
137             ( Jmespath->search( $acceptor->{'argument'}, $response ) eq
138 0 0         $acceptor->{'expected'} ) ? 1 : 0;
139 0           return $ret;
140             }
141             else {
142 0           return 0;
143             }
144             }
145              
146             sub match_error {
147 0     0 0   my ( $self, $acceptor, $response ) = @_;
148 0 0 0       if ( 'HASH' eq ref $response && exists $response->{'code'} ) {
149             my $ret =
150 0 0         ( $response->{'code'} eq $acceptor->{'expected'} ) ? 1 : 0;
151 0           return $ret;
152             }
153             else {
154 0           return 0;
155             }
156             }
157              
158             sub match_pathAll {
159 0     0 0   my ( $self, $acceptor, $response ) = @_;
160              
161 0           my $expression = Jmespath->compile( $acceptor->{'argument'} );
162 0           my $result = $expression->search($response);
163              
164 0 0 0       unless ( ref $result && 'ARRAY' eq ref $result
      0        
165             and length $result >= 1 )
166             {
167 0           return 0;
168             }
169              
170 0           for my $element ( $result->@* ) {
171 0 0         return 0 unless $element eq $acceptor->{'expected'};
172             }
173              
174 0           return 1;
175             }
176              
177             sub match_pathAny {
178 0     0 0   my ( $self, $acceptor, $response ) = @_;
179              
180 0           my $expression = Jmespath->compile( $acceptor->{'argument'} );
181 0           my $result = $expression->search($response);
182              
183 0 0 0       unless ( ref $result && 'ARRAY' eq ref $result
      0        
184             and length $result >= 1 )
185             {
186 0           return 0;
187             }
188              
189 0           for my $element ( $result->@* ) {
190 0 0         return 1 if $element eq $acceptor->{'expected'};
191             }
192              
193 0           return 0;
194             }
195              
196             sub match_status {
197 0     0 0   my ( $self, $acceptor, $response ) = @_;
198 0           return $response->{'http_status'} == $acceptor->{'expected'};
199             }
200              
201             1;