File Coverage

blib/lib/XAS/Lib/Service.pm
Criterion Covered Total %
statement 9 76 11.8
branch 1 8 12.5
condition n/a
subroutine 3 13 23.0
pod 3 4 75.0
total 16 101 15.8


line stmt bran cond sub pod time code
1             package XAS::Lib::Service;
2              
3             our $VERSION = '0.04';
4              
5 1     1   4 use POE;
  1         2  
  1         7  
6              
7             my ($mixin, $shutdown);
8              
9             BEGIN {
10              
11 1 50   1   334 if ($^O eq 'MSWin32') {
12              
13 0         0 $mixin = 'XAS::Lib::Service::Win32';
14 0         0 $shutdown = 25;
15              
16             } else {
17            
18 1         1 $mixin = 'XAS::Lib::Service::Unix';
19 1         53 $shutdown = 2;
20              
21             }
22              
23             }
24              
25             use XAS::Class
26 1         10 debug => 0,
27             version => $VERSION,
28             base => 'XAS::Lib::POE::Session',
29             utils => ':validation',
30             mixin => $mixin,
31             accessors => 'sessions',
32             mutators => 'last_state',
33             constants => 'DELIMITER',
34             vars => {
35             PARAMS => {
36             -poll_interval => { optional => 1, default => 2 },
37             -shutdown_interval => { optional => 1, default => $shutdown },
38             -alias => { optional => 1, default => 'services' },
39             }
40             }
41 1     1   4 ;
  1         1  
42              
43             #use Data::Dumper;
44              
45             # ----------------------------------------------------------------------
46             # Public Methods
47             # ----------------------------------------------------------------------
48              
49             sub register {
50 0     0 1   my $self = shift;
51 0           my ($sessions) = validate_params(\@_, [
52             (0) x (@_)
53             ]);
54              
55 0 0         if (ref($sessions) eq 'ARRAYREF') {
56              
57 0           foreach my $session (@$sessions) {
58              
59 0 0         next if ($session eq '');
60 0           push(@{$self->{'sessions'}}, $session);
  0            
61              
62             }
63              
64             } else {
65              
66 0           my @parts = split(DELIMITER, $sessions);
67              
68 0           foreach my $session (@parts) {
69              
70 0 0         next if ($session eq '');
71 0           push(@{$self->{'sessions'}}, $session);
  0            
72              
73             }
74              
75             }
76              
77             }
78              
79             sub unregister {
80 0     0 0   my $self = shift;
81 0           my $session = shift;
82              
83 0           my @sessions = grep { $_ ne $session } @{$self->{'sessions'}};
  0            
  0            
84 0           $self->{'sessions'} = \@sessions;
85              
86             }
87              
88             sub session_shutdown {
89 0     0 1   my $self = shift;
90              
91 0           $poe_kernel->delay('poll');
92 0           $self->SUPER::session_shutdown();
93              
94             }
95              
96             # ----------------------------------------------------------------------
97             # Public Events
98             # ----------------------------------------------------------------------
99              
100             # ----------------------------------------------------------------------
101             # Private Events
102             # ----------------------------------------------------------------------
103              
104             sub _session_init {
105 0     0     my ($self) = $_[OBJECT];
106              
107 0           my $alias = $self->alias;
108              
109 0           $self->log->debug("$alias: _session_init()");
110              
111 0           $poe_kernel->state('poll', $self);
112              
113 0           $self->last_state(SERVICE_START_PENDING);
114 0           $self->_current_state(SERVICE_START_PENDING);
115              
116 0           $self->init_service();
117 0           $self->session_initialize();
118              
119 0           $poe_kernel->post($alias, 'poll');
120              
121             }
122              
123             # ----------------------------------------------------------------------
124             # Private Methods
125             # ----------------------------------------------------------------------
126              
127             sub init {
128 0     0 1   my $class = shift;
129              
130 0           $poe_kernel->run(); # this only initializes POE
131              
132 0           my $self = $class->SUPER::init(@_);
133              
134 0           $self->{'sessions'} = ();
135              
136 0           return $self;
137              
138             }
139              
140             sub _service_startup {
141 0     0     my $self = shift;
142              
143 0           my $alias = $self->alias;
144              
145 0           $self->log->debug("$alias: _service_startup");
146              
147 0           foreach my $session (@{$self->{'sessions'}}) {
  0            
148              
149 0           $poe_kernel->post($session, 'session_startup');
150              
151             }
152              
153             }
154              
155             sub _service_shutdown {
156 0     0     my $self = shift;
157              
158 0           my $alias = $self->alias;
159              
160 0           $self->log->debug("$alias: _service_shutdown");
161              
162 0           foreach my $session (@{$self->{'sessions'}}) {
  0            
163              
164 0           $poe_kernel->post($session, 'session_shutdown');
165              
166             }
167              
168             }
169              
170             sub _service_idle {
171 0     0     my $self = shift;
172              
173 0           my $alias = $self->alias;
174              
175 0           $self->log->debug("$alias: _service_idle");
176              
177 0           foreach my $session (@{$self->{'sessions'}}) {
  0            
178              
179 0           $poe_kernel->post($session, 'session_idle');
180              
181             }
182              
183             }
184              
185             sub _service_paused {
186 0     0     my $self = shift;
187              
188 0           my $alias = $self->alias;
189              
190 0           $self->log->debug("$alias: _service_paused");
191              
192 0           foreach my $session (@{$self->{'sessions'}}) {
  0            
193              
194 0           $poe_kernel->post($session, 'session_pause');
195              
196             }
197              
198             }
199              
200             sub _service_resumed {
201 0     0     my $self = shift;
202              
203 0           my $alias = $self->alias;
204              
205 0           $self->log->debug("$alias: _service_resumed");
206              
207 0           foreach my $session (@{$self->{'sessions'}}) {
  0            
208              
209 0           $poe_kernel->post($session, 'session_resume');
210              
211             }
212              
213             }
214              
215             1;
216              
217             __END__
218              
219             =head1 NAME
220              
221             XAS::Lib::Service - A class to interact with Services
222              
223             =head1 SYNOPSIS
224              
225             use XAS::Lib::Service;
226              
227             my $service = XAS::Lib::Service->new(
228             -alias => 'service',
229             -poll_interval => 2,
230             -shutdown_interval => 25
231             );
232              
233             $service->run();
234              
235             =head1 DESCRIPTION
236              
237             This module provides a generic interface to "Services". A Service is
238             a managed background process. It responds to external events. On Windows
239             this would be responding to commands from the SCM. On Unix this would
240             be responding to a special set of signals. This module provides an
241             event loop that can interact those external events. The module
242             L<XAS::Lib::POE::Service|XAS::Lib::POE::Service> can interact with
243             this event loop.
244              
245             =head1 METHODS
246              
247             =head2 new()
248              
249             This method is used to initialize the service. This module inherits from
250             L<XAS::Lib::POE::Session|XAS::Lib::POE::Session>. It takes the following
251             parameters:
252              
253             =over 4
254              
255             =item B<-alias>
256              
257             The name of this POE session. Defaults to 'service';
258              
259             =item B<-poll_interval>
260              
261             This is the interval were the SCM sends SERVICE_RUNNING message. The
262             default is every 2 seconds.
263              
264             =item B<-shutdown_interval>
265              
266             This is the interval to pause the system shutdown so that the service
267             can cleanup after itself. The default is 25 seconds.
268              
269             =back
270              
271             =head2 register($session)
272              
273             This allows your process to register whatever modules you want events sent too.
274              
275             =over 4
276              
277             =item B<$session>
278              
279             This can be an array reference or a text string. The text string may be
280             delimited with commas. This will be the POE alias for each session.
281              
282             =back
283              
284             =head1 EVENTS
285              
286             When an external event happens this module will trap it and generate a POE
287             event. These events follow closely the model defined by the Windows Service
288             Control Manager interface. The event is then sent to all interested modules.
289             The following POE events have been defined:
290              
291             =head2 session_startup
292              
293             This is fired when your process starts up and is used to initialize what ever
294             processing you are going to do. On a network server, this may be opening a
295             port to listen on.
296              
297             =head2 session_shutdown
298              
299             This is fired when your process is shutting down.
300              
301             =head2 session_pause
302              
303             This is fired when your process needs to "pause".
304              
305             =head2 session_resume
306              
307             This is fired when your process needs to "resume".
308              
309             =head2 session_idle
310              
311             This is fired at every poll_interval.
312              
313             =head1 SEE ALSO
314              
315             =over 4
316              
317             =item L<XAS::Lib::Service::Unix|XAS::Lib::Service::Unix>
318              
319             =item L<XAS::Lib::Service::Win32|XAS::Lib::Service::Win32>
320              
321             =item L<XAS|XAS>
322              
323             =back
324              
325             =head1 AUTHOR
326              
327             Kevin L. Esteb, E<lt>kevin@kesteb.usE<gt>
328              
329             =head1 COPYRIGHT AND LICENSE
330              
331             Copyright (c) 2012-2015 Kevin L. Esteb
332              
333             This is free software; you can redistribute it and/or modify it under
334             the terms of the Artistic License 2.0. For details, see the full text
335             of the license at http://www.perlfoundation.org/artistic_license_2_0.
336              
337             =cut