File Coverage

blib/lib/IO/Iron/IronMQ/Client.pm
Criterion Covered Total %
statement 44 261 16.8
branch 0 50 0.0
condition 0 3 0.0
subroutine 16 41 39.0
pod 14 14 100.0
total 74 369 20.0


line stmt bran cond sub pod time code
1             package IO::Iron::IronMQ::Client;
2              
3             ## no critic (Documentation::RequirePodAtEnd)
4             ## no critic (Documentation::RequirePodSections)
5             ## no critic (ControlStructures::ProhibitPostfixControls)
6             ## no critic (Subroutines::RequireArgUnpacking)
7              
8 3     3   105592 use 5.010_000;
  3         28  
9 3     3   17 use strict;
  3         7  
  3         62  
10 3     3   13 use warnings;
  3         8  
  3         118  
11              
12             # Global creator
13 0         0 BEGIN {
14 3     3   454 use parent qw( IO::Iron::ClientBase ); # Inheritance
  3     0   295  
  3         15  
15             }
16              
17             # Global destructor
18       3     END {
19             }
20              
21             # ABSTRACT: IronMQ (Online Message Queue) Client.
22              
23             our $VERSION = '0.14'; # VERSION: generated by DZP::OurPkgVersion
24              
25 3     3   311 use Log::Any qw{$log};
  3         7  
  3         24  
26 3     3   563 use File::Spec;
  3         6  
  3         101  
27 3     3   532 use File::HomeDir;
  3         5683  
  3         281  
28 3     3   27 use Hash::Util 0.06 qw{lock_keys lock_keys_plus unlock_keys legal_keys};
  3         53  
  3         21  
29 3     3   683 use Carp::Assert;
  3         1216  
  3         20  
30 3     3   365 use Carp::Assert::More;
  3         7  
  3         601  
31 3     3   20 use English '-no_match_vars';
  3         7  
  3         16  
32 3     3   1687 use Params::Validate qw(:all);
  3         9054  
  3         517  
33              
34 3     3   1593 use IO::Iron::IronMQ::Api;
  3         7  
  3         93  
35 3     3   445 use IO::Iron::Common;
  3         7  
  3         124  
36             require IO::Iron::Connection;
37             require IO::Iron::IronMQ::Queue;
38              
39             # CONSTANTS for this package
40              
41             # DEFAULTS
42 3     3   458 use Const::Fast;
  3         2576  
  3         17  
43              
44             # Service specific!
45             const my $DEFAULT_API_VERSION => '3';
46             const my $DEFAULT_HOST => 'mq-aws-us-east-1-1.iron.io';
47              
48             sub new {
49 0     0 1   my $class = shift;
50             my %params = validate(
51             @_,
52             {
53 0           map { $_ => { type => SCALAR, optional => 1 }, } IO::Iron::Common::IRON_CLIENT_PARAMETERS(), ## no critic (ValuesAndExpressions::ProhibitCommaSeparatedStatements)
  0            
54             }
55             );
56              
57 0           $log->tracef( 'Entering new(%s, %s)', $class, \%params );
58 0           my $self = IO::Iron::ClientBase->new();
59              
60             # Add more keys to the self hash.
61             my @self_keys = (
62             'queues', # References to all objects created of class IO::Iron::IronMQ::Queue.
63 0           legal_keys( %{$self} ),
  0            
64             );
65 0           unlock_keys( %{$self} );
  0            
66 0           lock_keys_plus( %{$self}, @self_keys );
  0            
67 0           my $config = IO::Iron::Common::get_config(%params);
68 0           $log->debugf( 'The config: %s', $config );
69 0 0         $self->{'project_id'} = defined $config->{'project_id'} ? $config->{'project_id'} : undef;
70 0           $self->{'queues'} = [];
71 0           assert_nonblank( $self->{'project_id'}, 'self->{project_id} is not defined or is blank' );
72              
73 0           unlock_keys( %{$self} );
  0            
74 0           bless $self, $class;
75 0           lock_keys( %{$self}, @self_keys );
  0            
76              
77             # Set up the connection client
78             my $connection = IO::Iron::Connection->new(
79             {
80             'project_id' => $config->{'project_id'},
81             'token' => $config->{'token'},
82             'host' => defined $config->{'host'} ? $config->{'host'} : $DEFAULT_HOST,
83             'protocol' => $config->{'protocol'},
84             'port' => $config->{'port'},
85             'api_version' => defined $config->{'api_version'} ? $config->{'api_version'} : $DEFAULT_API_VERSION,
86             'timeout' => $config->{'timeout'},
87 0 0         'connector' => $params{'connector'},
    0          
88             }
89             );
90 0           $self->{'connection'} = $connection;
91             $log->debugf(
92             'IronMQ Connection created with config: (project_id=%s; token=%s; host=%s; timeout=%s).',
93             $config->{'project_id'},
94 0           $config->{'token'}, $config->{'host'}, $config->{'timeout'}
95             );
96 0           $log->tracef( 'Exiting new: %s', $self );
97 0           return $self;
98             }
99              
100             sub get_queue {
101 0     0 1   my $self = shift;
102 0           my %params = validate(
103             @_,
104             {
105             'name' => { type => SCALAR, }, # queue name.
106             }
107             );
108 0           $log->tracef( 'Entering get_queue(%s)', \%params );
109 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
110              
111 0           my $connection = $self->{'connection'};
112             my ( $http_status_code, $response_message ) =
113 0           $connection->perform_iron_action( IO::Iron::IronMQ::Api::IRONMQ_GET_QUEUE_INFO(), { '{Queue Name}' => $params{'name'}, } );
114 0           $self->{'last_http_status_code'} = $http_status_code;
115 0           my $new_queue = $response_message->{'queue'};
116 0           my $get_queue_name = $new_queue->{'name'};
117 0           my $queue = IO::Iron::IronMQ::Queue->new(
118             {
119             'ironmq_client' => $self, # Pass a reference to the parent object.
120             'name' => $get_queue_name,
121             'connection' => $connection,
122             }
123             );
124 0           $log->debugf( 'Created a new IO::Iron::IronMQ::Queue object (queue name=%s.', $get_queue_name );
125 0           $log->tracef( 'Exiting get_queue: %s', $queue );
126 0           return $queue;
127             }
128              
129             sub get_queues {
130 0     0 1   my $self = shift;
131 0           my %params = validate(
132             @_,
133             {
134             'prefix' => { type => SCALAR, optional => 1, },
135             }
136             );
137 0           $log->tracef('Entering get_queues()');
138              
139 0           my $previous = q{};
140 0           my @queue_names;
141 0           while ( my @names = $self->list_queues( 'per_page' => 30, 'previous' => $previous ) ) {
142 0           push @queue_names, @names;
143 0           $previous = $names[-1];
144             }
145 0           $log->debugf( 'Got a list of %d queue names.', scalar @queue_names );
146              
147 0           my @queues;
148 0           foreach my $queue_name (@queue_names) {
149 0           push @queues, $self->get_queue( 'name' => $queue_name );
150             }
151              
152 0           $log->tracef( 'Exiting get_queues: %s', \@queues );
153 0           return @queues;
154             }
155              
156             sub create_and_get_queue {
157 0     0 1   my $self = shift;
158             my %params = validate(
159             @_,
160             {
161             'name' => {
162             type => SCALAR,
163             callbacks => {
164 0     0     'RFC 3986 reserved character check' => sub { return !IO::Iron::Common::contains_rfc_3986_res_chars(shift) },
165             }
166             }, # queue name.
167 0           'message_timeout' => { type => SCALAR, optional => 1, },
168             'message_expiration' => { type => SCALAR, optional => 1, },
169             'type' => {
170             type => SCALAR,
171             optional => 1,
172             regex => qr/^(?:multicast|unicast|pull)$/msx, ## no critic (Variables::ProhibitPunctuationVars)
173             },
174             'push' => { type => HASHREF, optional => 1, },
175             'dead_letter' => { type => HASHREF, optional => 1, },
176             }
177             );
178 0           $log->tracef( 'Entering create_queue(%s)', \%params );
179 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
180              
181 0           my $connection = $self->{'connection'};
182 0           my %item_body;
183 0 0         $item_body{'message_timeout'} = $params{'message_timeout'} if ( $params{'message_timeout'} );
184 0 0         $item_body{'message_expiration'} = $params{'message_expiration'} if ( $params{'message_expiration'} );
185 0 0         $item_body{'type'} = $params{'type'} if ( $params{'type'} );
186 0 0         $item_body{'push'} = $params{'push'} if ( $params{'push'} );
187 0 0         $item_body{'dead_letter'} = $params{'dead_letter'} if ( $params{'dead_letter'} );
188             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
189             IO::Iron::IronMQ::Api::IRONMQ_CREATE_QUEUE(),
190             {
191 0           '{Queue Name}' => $params{'name'},
192             'body' => \%item_body,
193             }
194             );
195 0           $self->{'last_http_status_code'} = $http_status_code;
196             my $queue = IO::Iron::IronMQ::Queue->new(
197             {
198             'ironmq_client' => $self, # Pass a reference to the parent object.
199             'connection' => $connection,
200 0           'name' => $params{'name'},
201             }
202             );
203 0           $log->debugf( 'Created a new IO::Iron::IronMQ::Queue object (queue name=%s).', $queue->name() );
204 0           $log->tracef( 'Exiting create_queue: %s', $queue );
205 0           return $queue;
206             }
207              
208             sub create_queue {
209 0     0 1   my $self = shift;
210             my %params = validate(
211             @_,
212             {
213             'name' => {
214             type => SCALAR,
215             callbacks => {
216 0     0     'RFC 3986 reserved character check' => sub { return !IO::Iron::Common::contains_rfc_3986_res_chars(shift) },
217             }
218             }, # queue name.
219 0           'message_timeout' => { type => SCALAR, optional => 1, },
220             'message_expiration' => { type => SCALAR, optional => 1, },
221             'type' => {
222             type => SCALAR,
223             optional => 1,
224             regex => qr/^(?:multicast|unicast|pull)$/msx, ## no critic (Variables::ProhibitPunctuationVars)
225             },
226             'push' => { type => HASHREF, optional => 1, },
227             'dead_letter' => { type => HASHREF, optional => 1, },
228             }
229             );
230 0           $log->tracef( 'Entering create_queue(%s)', \%params );
231 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
232              
233 0           my $connection = $self->{'connection'};
234 0           my %item_body;
235 0 0         $item_body{'message_timeout'} = $params{'message_timeout'} if ( $params{'message_timeout'} );
236 0 0         $item_body{'message_expiration'} = $params{'message_expiration'} if ( $params{'message_expiration'} );
237 0 0         $item_body{'type'} = $params{'type'} if ( $params{'type'} );
238 0 0         $item_body{'push'} = $params{'push'} if ( $params{'push'} );
239 0 0         $item_body{'dead_letter'} = $params{'dead_letter'} if ( $params{'dead_letter'} );
240             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
241             IO::Iron::IronMQ::Api::IRONMQ_CREATE_QUEUE(),
242             {
243 0           '{Queue Name}' => $params{'name'},
244             'body' => \%item_body,
245             }
246             );
247 0           $self->{'last_http_status_code'} = $http_status_code;
248 0           $log->tracef( 'Exiting create_queue: %s', undef );
249 0           return;
250             }
251              
252             sub get_queue_info {
253 0     0 1   my $self = shift;
254 0           my %params = validate(
255             @_,
256             {
257             'name' => { type => SCALAR, }, # queue name.
258             }
259             );
260 0           $log->tracef( 'Entering get_queue_info(%s)', \%params );
261 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
262              
263 0           my $connection = $self->{'connection'};
264             my ( $http_status_code, $response_message ) =
265 0           $connection->perform_iron_action( IO::Iron::IronMQ::Api::IRONMQ_GET_QUEUE_INFO(), { '{Queue Name}' => $params{'name'}, } );
266 0           $self->{'last_http_status_code'} = $http_status_code;
267 0           my $info = $response_message;
268              
269             # {"id":"51be[...]","name":"Log_Test_Queue","size":0,"total_messages":3,"project_id":"51bd[...]"}
270 0           $log->debugf( 'Returned info about queue %s.', $params{'name'} );
271 0           $log->tracef( 'Exiting get_queue_info: %s', $info );
272 0           return $info;
273             }
274              
275             sub update_queue {
276 0     0 1   my $self = shift;
277             my %params = validate(
278             @_,
279             {
280             'name' => {
281             type => SCALAR,
282             callbacks => {
283 0     0     'RFC 3986 reserved character check' => sub { return !IO::Iron::Common::contains_rfc_3986_res_chars(shift) },
284             }
285             }, # queue name.
286 0           'message_timeout' => { type => SCALAR, optional => 1, },
287             'message_expiration' => { type => SCALAR, optional => 1, },
288             'push' => { type => HASHREF, optional => 1, },
289             'dead_letter' => { type => HASHREF, optional => 1, },
290             }
291             );
292 0           $log->tracef( 'Entering update_queue(%s)', \%params );
293 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
294              
295 0           my $connection = $self->{'connection'};
296 0           my %item_body;
297 0 0         $item_body{'message_timeout'} = $params{'message_timeout'} if ( $params{'message_timeout'} );
298 0 0         $item_body{'message_expiration'} = $params{'message_expiration'} if ( $params{'message_expiration'} );
299 0 0         $item_body{'push'} = $params{'push'} if ( $params{'push'} );
300 0 0         $item_body{'dead_letter'} = $params{'dead_letter'} if ( $params{'dead_letter'} );
301             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
302             IO::Iron::IronMQ::Api::IRONMQ_UPDATE_QUEUE(),
303             {
304 0           '{Queue Name}' => $params{'name'},
305             'body' => \%item_body,
306             }
307             );
308 0           $self->{'last_http_status_code'} = $http_status_code;
309 0           $log->tracef( 'Exiting update_queue: %s', undef );
310 0           return;
311             }
312              
313             sub delete_queue {
314 0     0 1   my $self = shift;
315             my %params = validate(
316             @_,
317             {
318             'name' => {
319             type => SCALAR,
320             callbacks => {
321 0     0     'RFC 3986 reserved character check' => sub { return !IO::Iron::Common::contains_rfc_3986_res_chars(shift) },
322 0     0     'Is longer than zero characters' => sub { return length shift },
323             }
324             }, # queue name.
325             }
326 0           );
327 0           $log->tracef( 'Entering delete_queue(%s)', \%params );
328              
329 0           my $connection = $self->{'connection'};
330             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
331             IO::Iron::IronMQ::Api::IRONMQ_DELETE_QUEUE(),
332             {
333 0           '{Queue Name}' => $params{'name'},
334             }
335             );
336 0           $self->{'last_http_status_code'} = $http_status_code;
337 0           $log->debugf( 'Deleted queue (queue name=%s).', $params{'name'} );
338 0           $log->tracef( 'Exiting delete_queue: %d', undef );
339 0           return;
340             }
341              
342             sub list_queues {
343 0     0 1   my $self = shift;
344 0           my %params = validate(
345             @_,
346             {
347             'per_page' => {
348             type => SCALAR,
349             optional => 0,
350             regex => qr/^[[:digit:]]{1,}$/msx, ## no critic (Variables::ProhibitPunctuationVars)
351             },
352             'previous' => { type => SCALAR, optional => 0, }, # Can be empty string.
353             'prefix' => { type => SCALAR, optional => 1, },
354             }
355             );
356 0           $log->tracef('Entering list_queues()');
357              
358 0           my @queues;
359 0           my $connection = $self->{'connection'};
360 0           my %query_params;
361 0 0         $query_params{'{per_page}'} = $params{'per_page'} if $params{'per_page'};
362 0 0         $query_params{'{previous}'} = $params{'previous'} if $params{'previous'};
363 0 0         $query_params{'{prefix}'} = $params{'prefix'} if $params{'prefix'};
364 0           my ( $http_status_code, $response_message ) =
365             $connection->perform_iron_action( IO::Iron::IronMQ::Api::IRONMQ_LIST_QUEUES(), {%query_params} );
366 0           $self->{'last_http_status_code'} = $http_status_code;
367              
368 0           foreach my $queue_info ( @{ $response_message->{'queues'} } ) {
  0            
369 0           my $queue_name = $queue_info->{'name'};
370 0           push @queues, $queue_name;
371             }
372              
373 0           $log->tracef( 'Exiting list_queues: %s', \@queues );
374 0           return @queues;
375             }
376              
377             sub add_subscribers {
378 0     0 1   my $self = shift;
379 0           my %params = validate(
380             @_,
381             {
382             'name' => { type => SCALAR, }, # queue name.
383             'subscribers' => { type => ARRAYREF, optional => 1 }
384             , # array of subscriber hashes containing a required "url" field and an optional "headers" map for custom headers.
385             }
386             );
387 0           $log->tracef( 'Entering add_subscribers(%s)', \%params );
388 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
389              
390 0           my $connection = $self->{'connection'};
391 0           my %item_body;
392 0 0         $item_body{'subscribers'} = $params{'subscribers'} if ( $params{'subscribers'} );
393             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
394             IO::Iron::IronMQ::Api::IRONMQ_ADD_SUBSCRIBERS_TO_A_MESSAGE_QUEUE(),
395             {
396 0           '{Queue Name}' => $params{'name'},
397             'body' => \%item_body,
398             }
399             );
400 0           $self->{'last_http_status_code'} = $http_status_code;
401              
402 0           $log->tracef( 'Exiting add_subscribers: %d', 1 );
403 0           return 1;
404             }
405              
406             # TODO Inform bug in documentation: does not return the queue info, returns: "{msg => 'Updated'}".
407              
408             sub delete_subscribers {
409 0     0 1   my $self = shift;
410 0           my %params = validate(
411             @_,
412             {
413             'name' => { type => SCALAR, }, # queue name.
414             'subscribers' => { type => ARRAYREF, optional => 1 }
415             , # array of subscriber hashes containing a required "url" field and an optional "headers" map for custom headers.
416             }
417             );
418 0           $log->tracef( 'Entering delete_subscribers(%s)', \%params );
419 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
420              
421 0           my $connection = $self->{'connection'};
422 0           my %item_body;
423 0 0         $item_body{'subscribers'} = $params{'subscribers'} if ( $params{'subscribers'} );
424             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
425             IO::Iron::IronMQ::Api::IRONMQ_DELETE_SUBSCRIBERS_FROM_A_MESSAGE_QUEUE(),
426             {
427 0           '{Queue Name}' => $params{'name'},
428             'body' => \%item_body,
429             }
430             );
431 0           $self->{'last_http_status_code'} = $http_status_code;
432              
433 0           $log->debugf( 'Deleted subscribers (queue name=%s).', $params{'name'} );
434 0           $log->tracef( 'Exiting delete_subscribers: %d', 1 );
435 0           return 1;
436             }
437              
438             sub add_alerts {
439 0     0 1   my $self = shift;
440             my %params = validate(
441             @_,
442             {
443             'name' => { type => SCALAR, }, # queue name.
444             'alerts' => {
445             type => ARRAYREF,
446             callbacks => {
447             'Assert item content' => sub {
448 0     0     foreach my $alert ( @{ $_[0] } ) {
  0            
449              
450             # TODO New function: Carp::Assert::More::assert_allowed(). Allowed keys in hash.
451 0           assert_exists(
452             $alert,
453             [ 'type', 'queue', 'trigger' ],
454             'Hash alert contains keys \'type\', \'queue\' and \'trigger\'.'
455             );
456             }
457 0           return 1;
458             }
459             }
460             }, # An array of alert hashes containing required "type", "queue", "trigger", and optional "direction", "snooze" fields. Maximum number of alerts is 5.
461             }
462 0           );
463 0           $log->tracef( 'Entering add_alerts(%s)', \%params );
464 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
465              
466 0           my $connection = $self->{'connection'};
467 0           my %item_body;
468 0           $item_body{'alerts'} = $params{'alerts'};
469             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
470             IO::Iron::IronMQ::Api::IRONMQ_ADD_ALERTS_TO_A_QUEUE(),
471             {
472 0           '{Queue Name}' => $params{'name'},
473             'body' => \%item_body,
474             }
475             );
476 0           $self->{'last_http_status_code'} = $http_status_code;
477              
478 0           $log->tracef( 'Exiting add_alerts: %d', 1 );
479 0           return 1;
480             }
481              
482             sub replace_alerts {
483 0     0 1   my $self = shift;
484             my %params = validate(
485             @_,
486             {
487             'name' => { type => SCALAR, }, # queue name.
488             'alerts' => {
489             type => ARRAYREF,
490             callbacks => {
491             'Assert item content' => sub {
492 0     0     foreach my $alert ( @{ $_[0] } ) {
  0            
493 0           assert_exists(
494             $alert,
495             [ 'type', 'queue', 'trigger' ],
496             'Hash alert contains keys \'type\', \'queue\' and \'trigger\'.'
497             );
498             }
499 0           return 1;
500             }
501             }
502             }, # An array of alert hashes containing required "type", "queue", "trigger", and optional "direction", "snooze" fields. Maximum number of alerts is 5.
503             }
504 0           );
505 0           $log->tracef( 'Entering replace_alerts(%s)', \%params );
506 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
507              
508 0           my $connection = $self->{'connection'};
509 0           my %item_body;
510 0           $item_body{'alerts'} = $params{'alerts'};
511             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
512             IO::Iron::IronMQ::Api::IRONMQ_REPLACE_ALERTS_ON_A_QUEUE(),
513             {
514 0           '{Queue Name}' => $params{'name'},
515             'body' => \%item_body,
516             }
517             );
518 0           $self->{'last_http_status_code'} = $http_status_code;
519              
520 0           $log->tracef( 'Exiting replace_alerts: %d', 1 );
521 0           return 1;
522             }
523              
524             sub delete_alerts {
525 0     0 1   my $self = shift;
526             my %params = validate(
527             @_,
528             {
529             'name' => { type => SCALAR, }, # queue name.
530             'alerts' => {
531             type => ARRAYREF,
532             optional => 1,
533             callbacks => {
534             'Either parameter \'alerts\' or \'id\'' => sub {
535 0 0   0     return exists $_[1]->{'id'} ? 0 : 1;
536             },
537             'Assert item content' => sub {
538 0     0     foreach my $alert ( @{ $_[0] } ) {
  0            
539 0           assert_exists( $alert, ['id'], 'Hash alert contains key \'id\'.' );
540             }
541 0           return 1;
542             }
543             },
544             }, # An array of alerts hashes containing "id" field.
545             'id' => {
546             type => SCALAR,
547             optional => 1,
548             callbacks => {
549             'Either parameter \'alerts\' or \'id\'' => sub {
550 0 0   0     return exists $_[1]->{'alerts'} ? 0 : 1;
551             },
552             },
553             }, # alert id.
554             # TODO New function: Params::Validate::validate(), mutually exclusive parameters.
555             }
556 0           );
557 0           $log->tracef( 'Entering delete_alerts(%s)', \%params );
558 0           assert_nonblank( $params{'name'}, 'Parameter \'name\' is a non blank string' );
559 0   0       assert( $params{'alerts'} || $params{'id'}, 'Have either parameter \'alerts\' or \'id\'.' );
560              
561 0           my $connection = $self->{'connection'};
562 0 0         if ( $params{'alerts'} ) {
563 0           my %item_body;
564 0           $item_body{'alerts'} = $params{'alerts'};
565             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
566             IO::Iron::IronMQ::Api::IRONMQ_REMOVE_ALERTS_FROM_A_QUEUE(),
567             {
568 0           '{Queue Name}' => $params{'name'},
569             'body' => \%item_body,
570             }
571             );
572 0           $self->{'last_http_status_code'} = $http_status_code;
573             }
574             else {
575             my ( $http_status_code, $response_message ) = $connection->perform_iron_action(
576             IO::Iron::IronMQ::Api::IRONMQ_REMOVE_ALERTS_FROM_A_QUEUE_BY_ID(),
577             {
578             '{Queue Name}' => $params{'name'},
579 0           '{Alert ID}' => $params{'id'},
580             }
581             );
582 0           $self->{'last_http_status_code'} = $http_status_code;
583             }
584              
585 0           $log->debugf( 'Deleted alerts (queue name=%s).', $params{'name'} );
586 0           $log->tracef( 'Exiting delete_alerts: %d', 1 );
587 0           return 1;
588             }
589              
590             1;
591              
592             __END__
593              
594             =pod
595              
596             =encoding UTF-8
597              
598             =head1 NAME
599              
600             IO::Iron::IronMQ::Client - IronMQ (Online Message Queue) Client.
601              
602             =head1 VERSION
603              
604             version 0.14
605              
606             =head1 SYNOPSIS
607              
608             require IO::Iron::IronMQ::Client;
609              
610             my $iron_mq_client = IO::Iron::IronMQ::Client->new();
611             my $iron_mq_queue_new = $iron_mq_client->create_queue('name' => 'My_Message_Queue');
612             # Or get an existing queue.
613             my $iron_mq_queue = $iron_mq_client->get_queue('name' => 'My_Message_Queue');
614             my $queue_info = $iron_mq_client->get_queue_info('name' => 'My_Message_Queue');
615             my $iron_mq_msg_send = IO::Iron::IronMQ::Message->new(
616             'body' => "My message",
617             );
618             my $msg_send_id = $iron_mq_queue->post_messages('messages' => [ $iron_mq_msg_send ]);
619             my $iron_mq_msg_peek = $iron_mq_queue->peek();
620             my @iron_mq_msgs_pull = $iron_mq_queue->reserve_messages( n => 1 );
621             my $pulled_msg_body = $iron_mq_msgs_pull[0]->body();
622             my $delete_ret = $iron_mq_queue->delete( 'ids' => [ $iron_mq_msgs_pull[0]->id() ]);
623             my $cleared = $iron_mq_queue->clear();
624             my $queue_deleted = $iron_mq_client->delete_queue('name' => 'My_Message_Queue');
625              
626             =head1 DESCRIPTION
627              
628             IO::Iron::IronMQ is a client for the IronMQ message queue at L<http://www.iron.io/|http://www.iron.io/>.
629             IronMQ is a cloud based message queue with a REST API.
630             IO::Iron::IronMQ creates a Perl object for interacting with IronMQ.
631             All IronMQ functions are available.
632              
633             The class IO::Iron::IronMQ::Client instantiates the 'project', IronMQ access configuration.
634              
635             =head2 IronMQ Message Queue
636              
637             L<http://www.iron.io/|http://www.iron.io/>
638              
639             IronMQ is a message queue as a service available to Internet connecting
640             applications via its REST interface. Built with distributed
641             cloud applications in mind, it provides on-demand message
642             queuing with HTTPS transport, one-time FIFO delivery, message persistence,
643             and cloud-optimized performance. [see L<http://www.iron.io/|http://www.iron.io/>]
644              
645             =head2 Using the IronMQ Client Library
646              
647             IO::Iron::IronMQ::Client is a normal Perl package meant to be used as an object.
648              
649             require IO::Iron::IronMQ::Client;
650             my $iron_mq_client = IO::Iron::IronMQ::Client->new( { } );
651              
652             The following parameters can be given to new() as items in the first parameter which is a hash.
653              
654             =over 8
655              
656             =item project_id, The ID of the project to use for requests.
657              
658             =item token, The OAuth token that is used to authenticate requests.
659              
660             =item host, The domain name the API can be located at. E.g. 'mq-aws-us-east-1.iron.io/1'.
661              
662             =item protocol, The protocol that will be used to communicate with the API. Defaults to "https".
663              
664             =item port, The port to connect to the API through. Defaults to 443.
665              
666             =item api_version, The version of the API to connect through. Defaults to the version supported by the client.
667              
668             =item timeout, REST client timeout (for REST calls accessing IronMQ.)
669              
670             =item config, Config filename with path if required.
671              
672             =back
673              
674             You can also give the parameters in the config file F<.iron.json>
675             (in home dir) or
676             F<iron.json> (in current dir) or as environmental variables. Please read
677             L<http://dev.iron.io/mq/reference/configuration/|http://dev.iron.io/mq/reference/configuration/>
678             for further details.
679              
680             After creating the client, the client can create a new message queue, get,
681             modify or delete an old one or get all the existing message queues within
682             the same project.
683              
684             The client has all the methods which interact with
685             queues; the queue (object of IO::Iron::IronMQ::Queue) has methods which involve
686             messages.
687              
688             If failed, the methods cause exception. After successfull REST API call,
689             the HTTP return code can be retrieved with method
690             last_http_status_code().
691              
692             # Create a new queue. (Parameter queue name;
693             # return an IO::Iron::IronMQ::Queue object)
694             my $iron_mq_queue = $iron_mq_client->create_and_get_queue(
695             'name' => 'My_Message_Queue',
696             );
697              
698             # Get an existing queue. (Parameter queue name;
699             # return an IO::Iron::IronMQ::Queue object)
700             my $iron_mq_queue = $iron_mq_client->get_queue( 'name' => 'My_Message_Queue');
701              
702             # Delete an existing queue. (Parameter queue name;
703             # return undef)
704             $iron_mq_client->delete_queue( 'name' => 'My_Message_Queue');
705              
706             # Get all the queues.
707             # Return a list of IO::Iron::IronMQ::Queue objects.
708             my @iron_mq_queues = $iron_mq_client->get_queues();
709              
710             # Get info about the queue
711             # (Return a hash containing items name, id, size, project, etc.).
712             my $queue_info = $iron_mq_client->get_queue_info( 'name' => 'My_Message_Queue');
713              
714             A IO::Iron::IronMQ::Queue object gives access to a single message queue.
715             With it you can do all the normal things one would with a message queue.
716              
717             Messages are objects of the class IO::Iron::IronMQ::Message. It contains
718             the following attributes:
719              
720             =over 8
721              
722             =item - body, Free text. If you want to put an object or a hash here, it needs to be serialized first; use e.g. JSON, Storable or YAML to stringify it. Then give the resulting string here.
723              
724             =item - delay, The item will not be available on the queue until this many seconds have passed.
725              
726             =item - push_headersn, Headers for push queues.
727              
728             =item - id, Message id from IronMQ (available after message has been pulled/peeked).
729              
730             =item - reserved_count, Not yet implemented. (available after message has been pulled/peeked).
731              
732             =item - reservation_id, Reservation id string from the queue.
733              
734             =back
735              
736             my $iron_mq_msg_send_01 = IO::Iron::IronMQ::Message->new(
737             'body' => "My message",
738             );
739             # Or
740             use YAML::Tiny;
741             %msg_body_hash_02 = (msg_body_text => 'My message 2', msg_body_item => {sub_item => 'Sub text'});
742             my $yaml = YAML::Tiny->new(); $yaml->[0] = \%msg_body_hash_02;
743             my $msg_body = $yaml->write_string();
744             my $iron_mq_msg_send_02 = IO::Iron::IronMQ::Message->new(
745             'body' => $msg_body,
746             'delay' => $msg_delay, # The item will not be available on the queue until this many seconds have passed.
747             );
748             # Return YAML serialized structure:
749             my $yaml_de = YAML::Tiny->new(); $yaml_de = $yaml_de->read_string($iron_mq_msg_send_02->body());
750              
751             IO::Iron::IronMQ::Queue objects are created by the client IO::Iron::IronMQ::Client.
752             With an IO::Iron::IronMQ::Queue object you can push messages to the queue,
753             or pull messages from it. The names push and pull are used because the
754             queue is likened to a pipe. The queue is like a FIFO pipe (first in, first out).
755              
756             Get queue name.
757              
758             my $queue_name = $iron_mq_queue->name();
759              
760             Add one or more messages to the queue. Returns the ids of the messages sent
761             or the number of sent messages.
762              
763             my $msg_send_id = $iron_mq_queue->post_messages( 'messages' => [ $iron_mq_msg_send_01 ] );
764             my @msg_send_ids = $iron_mq_queue->post_messages( 'messages' => [ $iron_mq_msg_send_01, $iron_mq_msg_send_02 ] );
765             my $number_of_msgs_sent = $iron_mq_queue->post_messages( 'messages' => [ $iron_mq_msg_send_01, $iron_mq_msg_send_02 ] );
766              
767             Read one or more messages from the queue and reserve them so another process
768             cannot access them. Parameters: n (number of messages you want, default 1,
769             maximum 100; if there is less, all available messages will be returned),
770             if no messages, an empty list will be returned,
771             timeout (After timeout (in seconds), item will be placed back onto queue,
772             default is 60 seconds, minimum is 30 seconds, and maximum is 86,400 seconds (24 hours)).
773              
774             my @iron_mq_msg_pulls = $iron_mq_queue->reserve_messages( n => 10, timeout => 120 );
775              
776             Read one or more messages from the queue but don't reserve them.
777             Parameters: n (number of messages you want, default 1, maximum 100; if there
778             is less, all available messages will be returned),
779             if no messages, an empty list will be returned.
780              
781             my @iron_mq_msg_peeks = $iron_mq_queue->peek( n => 10 );
782              
783             Delete one or more messages from the queue. Call this when you have
784             processed the messages. Returns the ids of the messages deleted
785             or the number of deleted messages.
786              
787             my $deleted_msg_id = $iron_mq_queue->delete( 'ids' => [ $msg_id_01 ] );
788             my @deleted_msg_ids = $iron_mq_queue->delete( 'ids' => [ $msg_id_01, $msg_id_02 ] );
789             my $number_of_msgs_deleted = $iron_mq_queue->delete( 'ids' => [ $msg_id_01, $msg_id_02 ] );
790              
791             Release one or more messages back to the queue.
792             Releasing a reserved message unreserves the message and puts
793             it back on the queue as if the message had timed out.
794             Delay: The item will not be available on the queue until this
795             many seconds have passed. Default is 0 seconds.
796             Maximum is 604,800 seconds (7 days).
797              
798             Returns 1.
799              
800             my $released_msg = $iron_mq_queue->release( 'id' => $msg_id_01, 'delay' => $delay );
801              
802             Touch one or more messages in the queue. Touching a reserved message extends
803             its timeout to the duration specified when the message was created.
804             Default is 60 seconds.
805             Returns 1.
806              
807             my $touched_msg = $iron_mq_queue->touch_message( 'id' => $msg_id_01 );
808              
809             Clear all messages from the queue: delete all messages,
810             whether they are reserved or not.
811              
812             my $cleared = $iron_mq_queue->clear_messages();
813              
814             Get queue size.
815              
816             my $size = $iron_mq_queue->size();
817              
818             =head3 Push Queue Commands
819              
820             Get push status for a message. Retrieve the push status for a
821             particular message which will let you know which subscribers
822             have received the message, which have failed, how many times
823             it's tried to be delivered and the status code returned from
824             the endpoint.
825              
826             my $info = $iron_mq_queue->get_push_statuses( 'id' => $msg_id );
827             my @subscribers = (@{info->{'subscribers'}});
828              
829             Acknowledge / Delete Push Message for a Subscriber.
830             This is only for use with long running processes that have
831             previously returned a 202.
832              
833             my $info = $iron_mq_queue->get_push_statuses( 'id' => $msg_id );
834             my @subscribers = (@{info->{'subscribers'}});
835             my $push_acknowledged = $iron_mq_queue->delete_push_message(
836             'id' => $msg_id, 'subscriber' => $subscribers[0]->{'id'}
837             );
838              
839             Add Subscribers to a Queue.
840              
841             my $add_ret_val = $iron_mq_queue->add_subscribers(
842             'name' => $queue_name,
843             'subscribers' => [
844             { 'url' => "ironmq://project_id:token\@host/queue_name" },
845             { 'url' => "ironmq:///$queue_name_02" },
846             ],
847             );
848              
849             Remove Subscribers from a Queue
850              
851             my $del_ret_val = $iron_mq_client->delete_subscribers(
852             'name' => $queue_name,
853             'subscribers' => [
854             { 'url' => "ironmq:///$queue_name" },
855             ],
856             );
857              
858             =head3 Queue Alerts
859              
860             Add Alerts to a Queue. This is for Pull Queue only.
861              
862             my $alert_added = $iron_mq_client->add_alerts(
863             'name' => $normal_queue->name(),
864             'alerts' => [
865             {
866             'type' => 'fixed',
867             'queue' => $alert_queue->name(),
868             'trigger' => 1,
869             'direction' => 'asc',
870             'snooze' => 0,
871             }
872             ],
873             );
874              
875             Replace alerts. Change the existing alerts to the given ones.
876              
877             my $alert_replaced = $iron_mq_client->replace_alerts(
878             'name' => $normal_queue->name(),
879             'alerts' => [
880             {
881             'type' => 'fixed',
882             'queue' => $alert_queue->name(),
883             'trigger' => 2,
884             'direction' => 'desc',
885             'snooze' => 0,
886             },
887             {
888             'type' => 'fixed',
889             'queue' => $alert_queue->name(),
890             'trigger' => 5,
891             'direction' => 'desc',
892             'snooze' => 5,
893             },
894             ],
895             );
896              
897             Delete alerts. You can either give an array containing items (hashes)
898             which contain key 'id', or delete only one alert with the parameter 'id'.
899              
900             my $alert_deleted = $iron_mq_client->delete_alerts(
901             'name' => $normal_queue->name(),
902             'alerts' => [
903             { 'id' => $alert_id, },
904             ],
905             );
906              
907             Or:
908              
909             $alert_deleted = $iron_mq_client->delete_alerts(
910             'name' => $normal_queue->name(),
911             'id' => $alert_id,
912             );
913              
914             =head3 Exceptions
915              
916             A REST call to IronMQ server may fail for several reason.
917             All failures generate an exception using the L<Exception::Class|Exception::Class> package.
918             Class IronHTTPCallException contains the field status_code, response_message and error.
919             Error is formatted as such: IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>.
920              
921             use Try::Tiny;
922             use Scalar::Util qw{blessed};
923             try {
924             my $queried_iron_mq_queue_01 = $iron_mq_client->get_queue($unique_queue_name_01);
925             }
926             catch {
927             die $_ unless blessed $_ && $_->can('rethrow');
928             if ( $_->isa('IronHTTPCallException') ) {
929             if ($_->status_code == 404) {
930             print "Bad things! Can not just find the catch in this!\n";
931             }
932             }
933             else {
934             $_->rethrow; # Push the error upwards.
935             }
936             };
937              
938             =for stopwords IronMQ API HTTPS optimized OAuth https config Config filename
939              
940             =for stopwords json dir successfull serialized JSON Storable YAML stringify
941              
942             =for stopwords unreserves IronHTTPCallException Params succcessful Iron.io
943              
944             =for stopwords Mikko Koivunalho perldoc CPAN AnnoCPAN ACKNOWLEDGMENTS
945              
946             =for stopwords TODO semafores tradename licensable MERCHANTABILITY
947              
948             =for stopwords lexicographically
949              
950             =head1 REQUIREMENTS
951              
952             See L<IO::Iron|IO::Iron> for requirements.
953              
954             =head1 SUBROUTINES/METHODS
955              
956             =head2 new
957              
958             Creator function.
959              
960             =head2 get_queue
961              
962             Return a IO::Iron::IronMQ::Queue object representing
963             a particular message queue.
964              
965             =over 8
966              
967             =item Params: queue name. Queue must exist. If not, fails with an exception.
968              
969             =item Return: IO::Iron::IronMQ::Queue object.
970              
971             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
972              
973             =back
974              
975             =head2 get_queues
976              
977             Return a IO::Iron::IronMQ::Queue objects representing message queues.
978             Not paginated; you get all the queues! Heavy because every queue must
979             separately be queried in IronMQ v3.
980              
981             =over 8
982              
983             =item Params: prefix
984              
985             =item Return: List of IO::Iron::IronMQ::Queue objects.
986              
987             =back
988              
989             =head2 create_and_get_queue
990              
991             Return a IO::Iron::IronMQ::Queue object. Throws if fails.
992             Combines create_queue() and get_queue() (which hides get_queue_info()).
993              
994             URL format for subscribers to Iron.io systems:
995             [ironmq_or_ironworker]://[project_id:token]@[host]/queue_or_worker_name
996              
997             =over 8
998              
999             =item Params: name, message_timeout, message_expiration, type, push { subscribers, retries, retries_delay, error_queue }, dead_letter { queue_name, max_reservations }.
1000              
1001             =item Return: IO::Iron::IronMQ::Queue object.
1002              
1003             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
1004              
1005             =back
1006              
1007             =head2 create_queue
1008              
1009             Return nothing. Throws if fails.
1010              
1011             URL format for subscribers to Iron.io systems:
1012             [ironmq_or_ironworker]://[project_id:token]@[host]/queue_or_worker_name
1013              
1014             =over 8
1015              
1016             =item Params: name, message_timeout, message_expiration, type, push { subscribers, retries, retries_delay, error_queue }, dead_letter { queue_name, max_reservations }.
1017              
1018             =item Return: undefined.
1019              
1020             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
1021              
1022             =back
1023              
1024             =head2 get_queue_info
1025              
1026             =over 8
1027              
1028             =item Params: queue name.
1029              
1030             =item Return: a hash containing info about queue.
1031              
1032             =back
1033              
1034             =head2 update_queue
1035              
1036             Update a queue. Return nothing. Throw if fails.
1037              
1038             =over 8
1039              
1040             =item Params: name, subscribers, push_type, retries, retries_delay, error_queue.
1041              
1042             =item Return: undefined.
1043              
1044             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
1045              
1046             =back
1047              
1048             =head2 delete_queue
1049              
1050             Delete an IronMQ queue. Return undefined. Throw if fails.
1051              
1052             =over 8
1053              
1054             =item Params: queue name. Queue must exist. If not, fails with an exception.
1055              
1056             =item Return: undefined.
1057              
1058             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
1059              
1060             =back
1061              
1062             =head2 list_queues
1063              
1064             Return a list of queue names.
1065              
1066             Paginated with per_page and previous
1067             (this is the last queue on the previous page, it will start from the next one.
1068             If queue with specified name does not exist result will contain
1069             first per_page queues that lexicographically greater than previous).
1070              
1071             =over 8
1072              
1073             =item Params: per_page, previous, prefix.
1074              
1075             =item Return: List.
1076              
1077             =back
1078              
1079             =head2 add_subscribers
1080              
1081             Add subscribers to a push queue.
1082              
1083             =over 8
1084              
1085             =item Params: name, subscribers.
1086              
1087             =item Returns 1 if succcessful
1088              
1089             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
1090              
1091             =back
1092              
1093             =head2 delete_subscribers
1094              
1095             Delete the given subscribers from the queue.
1096              
1097             =over 8
1098              
1099             =item Params: name, subscribers.
1100              
1101             =item Returns 1 if succcessful
1102              
1103             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
1104              
1105             =back
1106              
1107             =head2 add_alerts
1108              
1109             Add alerts to a queue.
1110              
1111             =over 8
1112              
1113             =item Params: name, alerts.
1114              
1115             =item Returns 1 if succcessful
1116              
1117             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
1118              
1119             =back
1120              
1121             =head2 replace_alerts
1122              
1123             Replace alerts to a queue. Replace the old alerts (if any) with these new ones.
1124              
1125             =over 8
1126              
1127             =item Params: name, alerts.
1128              
1129             =item Returns 1 if succcessful
1130              
1131             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
1132              
1133             =back
1134              
1135             =head2 delete_alerts
1136              
1137             Delete the given alerts from the queue.
1138              
1139             =over 8
1140              
1141             =item Params: name, alerts.
1142              
1143             =item Returns 1 if successful
1144              
1145             =item Exception: IronHTTPCallException if fails. (IronHTTPCallException: status_code=<HTTP status code> response_message=<response_message>)
1146              
1147             =back
1148              
1149             =head1 AUTHOR
1150              
1151             Mikko Koivunalho <mikko.koivunalho@iki.fi>
1152              
1153             =head1 BUGS
1154              
1155             Please report any bugs or feature requests to bug-io-iron@rt.cpan.org or through the web interface at:
1156             http://rt.cpan.org/Public/Dist/Display.html?Name=IO-Iron
1157              
1158             =head1 COPYRIGHT AND LICENSE
1159              
1160             This software is copyright (c) 2023 by Mikko Koivunalho.
1161              
1162             This is free software; you can redistribute it and/or modify it under
1163             the same terms as the Perl 5 programming language system itself.
1164              
1165             The full text of the license can be found in the
1166             F<LICENSE> file included with this distribution.
1167              
1168             =cut