File Coverage

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