File Coverage

blib/lib/SRS/EPP/Session/BackendQ.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1              
2             package SRS::EPP::Session::BackendQ;
3             {
4             $SRS::EPP::Session::BackendQ::VERSION = '0.22';
5             }
6              
7 2     2   24843 use SRS::EPP::SRSRequest;
  0            
  0            
8             use SRS::EPP::SRSResponse;
9             use SRS::EPP::Command;
10              
11             use Moose;
12             use MooseX::Params::Validate;
13              
14             has 'queue' =>
15             is => "ro",
16             isa => "ArrayRef[ArrayRef[SRS::EPP::SRSRequest]]",
17             default => sub { [] },
18             ;
19              
20             has 'owner' =>
21             is => "ro",
22             isa => "ArrayRef[SRS::EPP::Command]",
23             default => sub { [] },
24             ;
25              
26             has 'responses' =>
27             is => "ro",
28             isa => "ArrayRef[ArrayRef[SRS::EPP::SRSResponse]]",
29             default => sub { [] },
30             ;
31              
32             has 'sent' =>
33             is => "rw",
34             isa => "Int",
35             default => 0,
36             ;
37              
38             has 'session' =>
39             is => "ro",
40             isa => "SRS::EPP::Session",
41             ;
42              
43             # add a response corresponding to a request
44             sub queue_backend_request {
45             my $self = shift;
46            
47             my ( $cmd ) = pos_validated_list(
48             [shift],
49             { isa => 'SRS::EPP::Command' },
50             );
51             my @rq = @_;
52            
53             push @{ $self->queue }, \@rq;
54             push @{ $self->responses }, [];
55             push @{ $self->owner }, $cmd;
56             }
57              
58             use List::Util qw(sum);
59              
60             sub queue_size {
61             my $self = shift;
62            
63             sum 0, map { scalar @$_ } @{$self->queue};
64             }
65              
66             sub queue_flat {
67             my $self = shift;
68            
69             map {@$_} @{$self->queue};
70             }
71              
72             # get the next N backend messages to be sent; marks them as sent
73             sub backend_next {
74             my $self = shift;
75            
76             my ( $how_many ) = pos_validated_list(
77             \@_,
78             { isa => 'Int', default => 1 },
79             );
80            
81             return unless $how_many;
82             my $sent = $self->sent;
83             my $waiting = $self->queue_size - $sent;
84             $how_many = $waiting if $how_many > $waiting;
85             my @rv = ($self->queue_flat)[ $sent .. $sent + $how_many - 1 ];
86             $self->sent($sent + @rv);
87             return @rv;
88             }
89              
90             sub backend_pending {
91             my $self = shift;
92            
93             my $sent = $self->sent;
94             my $waiting = $self->queue_size - $sent;
95             return $waiting;
96             }
97              
98             # add a response corresponding to a request - must be in order as
99             # there is no other way to correlate read-only responses with their
100             # requests (no client_tx_id in SRS requests)
101             sub add_backend_response {
102             my $self = shift;
103            
104             my ( $request, $response ) = pos_validated_list(
105             \@_,
106             { isa => 'SRS::EPP::SRSRequest' },
107             { isa => 'SRS::EPP::SRSResponse' },
108             );
109            
110             my $rq_a = $self->queue->[0];
111             my $rs_a = $self->responses->[0];
112             for ( my $i = 0; $i <= $#$rq_a; $i++ ) {
113             if ( $rq_a->[$i] == $request ) {
114             $rs_a->[$i] = $response;
115             }
116             }
117             }
118              
119             sub backend_response_ready {
120             my $self = shift;
121            
122             my $rq_a = $self->queue->[0]
123             or return;
124             my $rs_a = $self->responses->[0];
125             @$rq_a == @$rs_a;
126             }
127              
128             sub dequeue_backend_response {
129             my $self = shift;
130            
131             if ( $self->backend_response_ready ) {
132             my $rq_a = shift @{ $self->queue };
133             my $owner = shift @{ $self->owner };
134             my $rs_a = shift @{ $self->responses };
135             my $sent = $self->sent;
136             $sent -= scalar @$rq_a;
137             if ( $sent < 0 ) {
138             warn "Bug: sent < 0 ?";
139             $sent = 0;
140             }
141             $self->sent($sent);
142              
143             if (wantarray) {
144             ($owner, @$rs_a);
145             }
146             else {
147             $rs_a;
148             }
149             }
150             else {
151             ();
152             }
153             }
154              
155             # Get the command object that 'owns' a SRS request
156             sub get_owner_of_request {
157             my $self = shift;
158            
159             my ( $request ) = pos_validated_list(
160             \@_,
161             { isa => 'SRS::EPP::SRSRequest' },
162             );
163            
164             my @queue = @{ $self->queue };
165             for my $i (0 .. $#queue) {
166             next unless ref $queue[$i] eq 'ARRAY';
167             foreach my $rq (@{$queue[$i]}) {
168             if ($rq->message->unique_id eq $request->message->unique_id) {
169             return $self->owner->[$i];
170             }
171             }
172             }
173             }
174              
175             1;
176              
177             __END__
178              
179             =head1 NAME
180              
181             SRS::EPP::Session::BackendQ - manage tx queue for back-end processing
182              
183             =head1 SYNOPSIS
184              
185             my $q = SRS::EPP::Session::BackendQ->new( session => $session );
186              
187             # put requests on queue
188             $q->queue_backend_request( $epp_command, @srs_requests );
189              
190             # pull up to 6 requests off queue for processing
191             my @rq = $q->backend_next( 6 );
192              
193             # put responses in, one by one.
194             for (1..6) {
195             $q->add_backend_response( $rq[$i], $rs[$i] );
196             }
197              
198             # if a message has had all its requests answered, it can be dequeued
199             ($epp_command, @srs_responses)
200             = $q->dequeue_backend_response();
201              
202             =head1 DESCRIPTION
203              
204             This class implements a simple FIFO queue, but with small
205             customizations to operation to suit the use case of the SRS EPP Proxy
206             tracking the requests it sends to the back-end.
207              
208             =head1 SEE ALSO
209              
210             L<SRS::EPP::Session>
211              
212             =head1 AUTHOR AND LICENCE
213              
214             Development commissioned by NZ Registry Services, and carried out by
215             Catalyst IT - L<http://www.catalyst.net.nz/>
216              
217             Copyright 2009, 2010, NZ Registry Services. This module is licensed
218             under the Artistic License v2.0, which permits relicensing under other
219             Free Software licenses.
220              
221             =cut
222              
223              
224             # Local Variables:
225             # mode:cperl
226             # indent-tabs-mode: t
227             # cperl-continued-statement-offset: 8
228             # cperl-brace-offset: 0
229             # cperl-close-paren-offset: 0
230             # cperl-continued-brace-offset: 0
231             # cperl-continued-statement-offset: 8
232             # cperl-extra-newline-before-brace: nil
233             # cperl-indent-level: 8
234             # cperl-indent-parens-as-block: t
235             # cperl-indent-wrt-brace: nil
236             # cperl-label-offset: -8
237             # cperl-merge-trailing-else: t
238             # End: