File Coverage

lib/MooseX/Workers.pm
Criterion Covered Total %
statement 24 27 88.8
branch 2 2 100.0
condition n/a
subroutine 10 12 83.3
pod 6 7 85.7
total 42 48 87.5


line stmt bran cond sub pod time code
1             package MooseX::Workers;
2 17     17   1063956 use Moose::Role;
  17         468193  
  17         70  
3 17     17   86311 use MooseX::Workers::Job;
  17         39  
  17         969  
4             our $VERSION = '0.15_01'; # http://www.cpan.org/modules/04pause.html - Developer releases
5              
6 17     17   8060 use MooseX::Workers::Engine;
  17         44  
  17         6171  
7              
8             has _ctor_params => (
9             is => 'ro',
10             isa => 'HashRef',
11             lazy => 1,
12             default => sub { {} },
13             );
14              
15             around BUILDARGS => sub {
16             my ($orig, $class, %args) = @_;
17              
18             shift;
19             shift;
20            
21             return $class->$orig( _ctor_params => \%args, @_ );
22             };
23              
24             has Engine => (
25             isa => 'MooseX::Workers::Engine',
26             is => 'ro',
27             lazy => 1,
28             required => 1,
29             builder => '_build_Engine',
30             handles => [
31             qw(
32             max_workers
33             has_workers
34             num_workers
35             put_worker
36             kill_worker
37             get_worker
38             )
39             ],
40             );
41             sub _build_Engine {
42 19     19   36 my $self = shift;
43 19         60 my @args;
44 19 100       386 push @args, max_workers => $self->_ctor_params->{max_workers} if exists $self->_ctor_params->{max_workers};
45 19         236 MooseX::Workers::Engine->new( visitor => $self, @args );
46             }
47              
48             sub spawn {
49 7     7 1 6200 my ( $self, $cmd, $args ) = @_;
50 7         140 return $self->Engine->call( add_worker => $cmd => $args );
51             }
52              
53             __PACKAGE__->meta->add_method( 'fork' => __PACKAGE__->can('spawn') );
54              
55             sub run_command {
56 5     5 1 8161 my ( $self, $cmd ) = @_;
57 5         103 $self->Engine->yield( add_worker => $cmd );
58             }
59              
60             sub enqueue {
61 61     61 1 2499 my ( $self, $cmd ) = @_;
62 61         1082 $self->Engine->call( add_worker => $cmd, { enqueue => 1 } );
63             }
64              
65             sub check_worker_threshold {
66 0     0 1 0 return $_[0]->num_workers >= $_[0]->max_workers;
67             }
68              
69             sub check_worker_threashold {
70 0     0 0 0 warn 'check_worker_threashold (note the typo) is deprecated '
71             . 'please use check_worker_threshold instead';
72 0         0 shift->check_worker_threshold;
73             }
74              
75 60     60 1 205 sub stdout_filter { undef }
76 71     71 1 198 sub stderr_filter { undef }
77              
78 17     17   141 no Moose::Role;
  17         21  
  17         152  
79             1;
80             __END__
81              
82             =head1 NAME
83              
84             MooseX::Workers - Simple sub-process management for asynchronous tasks
85              
86             =head1 SYNOPSIS
87              
88             EXAMPLE #1:
89             package Manager;
90             # This example prints output from the children normally on both STDOUT and STDERR
91              
92             use Moose;
93             with qw(MooseX::Workers);
94              
95             sub run {
96             $_[0]->spawn( sub { sleep 3; print "Hello World\n" } );
97             warn "Running now ... ";
98             POE::Kernel->run();
99             }
100              
101             # Implement our Interface
102             sub worker_stdout { shift; warn join ' ', @_; }
103             sub worker_stderr { shift; warn join ' ', @_; }
104              
105             sub worker_manager_start { warn 'started worker manager' }
106             sub worker_manager_stop { warn 'stopped worker manager' }
107              
108             sub max_workers_reached { warn 'maximum worker count reached' }
109             sub worker_error { shift; warn join ' ', @_; }
110             sub worker_done { shift; warn join ' ', @_; }
111             sub worker_started { shift; warn join ' ', @_; }
112             sub sig_child { shift; warn join ' ', @_; }
113             sub sig_TERM { shift; warn 'Handled TERM' }
114              
115             no Moose;
116              
117             Manager->new->run();
118              
119              
120             EXAMPLE #2:
121             package Manager;
122              
123             # This example prints output from the children normally on
124             # STDERR but uses STDOUT to returns a hashref from the child to
125             # the parent
126              
127             use Moose;
128             with qw(MooseX::Workers);
129             use POE qw(Filter::Reference Filter::Line);
130              
131             sub run {
132             $_[0]->spawn(
133             sub {
134             sleep 3;
135              
136             # Return a hashref (arrayref, whatever) to the parent using P::F::Reference
137             print @{POE::Filter::Reference->new->put([ {msg => "Hello World"} ])}; # Note the [] around the return val
138              
139             # Print normally using P::F::Line (shown for
140             # completeness; in practice, just don't bother
141             # defining the _filter method
142             #
143             print STDERR "Hey look, an error message";
144             }
145             );
146              
147             POE::Kernel->run();
148             }
149              
150             # Implement our Interface
151             # These two are both optional; if defined (as here), they
152             # should return a subclass of POE::Filter.
153             sub stdout_filter { POE::Filter::Reference->new }
154             sub stderr_filter { POE::Filter::Line->new }
155              
156             sub worker_stdout {
157             my ( $self, $result ) = @_; # $result will be a hashref: {msg => "Hello World"}
158             print $result->{msg};
159              
160             # Note that you can do more than just print the message --
161             # e.g. this is the way to return data from the children for
162             # accumulation in the parent.
163             }
164             sub worker_stderr {
165             my ( $self, $stderr_msg ) = @_; # $stderr_msg will be a string: "Hey look, an error message";
166             warn $stderr_msg;
167             }
168              
169             # From here down, this is identical to the previous example.
170             sub worker_manager_start { warn 'started worker manager' }
171             sub worker_manager_stop { warn 'stopped worker manager' }
172              
173             sub max_workers_reached { warn 'maximum worker count reached' }
174             sub worker_error { shift; warn join ' ', @_; }
175             sub worker_done { shift; warn join ' ', @_; }
176             sub worker_started { shift; warn join ' ', @_; }
177             sub sig_child { shift; warn join ' ', @_; }
178             sub sig_TERM { shift; warn 'Handled TERM' }
179              
180             no Moose;
181              
182             Manager->new->run();
183              
184             =head1 DESCRIPTION
185              
186             MooseX::Workers is a Role that provides easy delegation of long-running tasks
187             into a managed child process. Process management is taken care of via POE and its
188             POE::Wheel::Run module.
189              
190             =head1 METHODS
191              
192             =over
193              
194             =item spawn ($command)
195              
196             =item fork ($command)
197              
198             =item run_command ($command)
199              
200             These three methods are the whole point of this module.
201             They pass $command through to the MooseX::Worker::Engine which will take
202             care of running $command for you.
203              
204             spawn() and fork() both invoke L<POE::Kernel> call(), which is synchronous.
205              
206             run_command() invokes L<POE::Kernel> yield(), which is asynchronous.
207              
208             If max_workers() has been reached, run_command() warns and does nothing. It is up to you to re-submit
209             $command. See enqueue() if you want us to run $command as soon as another worker is free.
210              
211             =item enqueue($command)
212              
213             Just like run_command(), only that if max_workers() has been set and that number of workers
214             has been reached, then we add $command to a FIFO command queue. As soon as any running
215             worker exits, the first $command in queue (if any) will be run.
216              
217             =item check_worker_threshold
218              
219             This will check to see how many workers you have compared to the max_workers limit. It returns true
220             if the $num_workers is >= $max_workers;
221              
222             =item max_workers($count)
223              
224             An accessor for the maximum number of workers. This is delegated to the MooseX::Workers::Engine object.
225              
226             =item has_workers
227              
228             Check to see if we have *any* workers currently. This is delegated to the MooseX::Workers::Engine object.
229              
230             =item num_workers
231              
232             Return the current number of workers. This is delegated to the MooseX::Workers::Engine object.
233              
234             =item meta
235              
236             The Metaclass for MooseX::Workers::Engine see Moose's documentation.
237              
238             =back
239              
240             =head1 INTERFACE
241              
242             MooseX::Worker::Engine supports the following callbacks:
243              
244             =over
245              
246             =item worker_manager_start
247              
248             Called when the managing session is started
249              
250             =item worker_manager_stop
251              
252             Called when the managing session stops
253              
254             =item max_workers_reached
255              
256             Called when we reach the maximum number of workers
257              
258             =item stdout_filter
259              
260             OPTIONAL. If defined, this should return an object that isa
261             POE::Filter. If it doesn't, the results are undefined. Anything that
262             a child proc sends on STDOUT will be passed through the relevant
263             filter.
264              
265             =item stderr_filter
266              
267             OPTIONAL. If defined, this should return an object that isa
268             POE::Filter. If it doesn't, the results are undefined. Anything that
269             a child proc sends on STDERR will be passed through the relevant
270             filter.
271              
272             =item worker_stdout
273              
274             Called when a child prints to STDOUT. If C<stdout_filter> was
275             defined, the output will be filtered appropriately, as described
276             above. This is useful to allow child processes to return data to the
277             parent (generally via POE::Filter::Reference).
278              
279             =item worker_stderr
280              
281             Called when a child prints to STDERR. Filtered through the result of
282             C<stderr_filter> if that method is defined.
283              
284             =item worker_error
285              
286             Called when there is an error condition detected with the child.
287              
288             =item worker_done
289              
290             Called when a worker completes $command
291              
292             =item worker_started
293              
294             Called when a worker starts $command
295              
296             =item sig_child
297              
298             Called when the mangaging session recieves a SIG CHLD event
299              
300             =item sig_*
301              
302             Called when the underlying POE Kernel receives a signal; this is not limited to
303             OS signals (ie. what you'd usually handle in Perl's %SIG) so will also accept
304             arbitrary POE signals (sent via POE::Kernel->signal), but does exclude
305             SIGCHLD/SIGCHILD, which is instead handled by sig_child above.
306              
307             These interface methods are automatically inserted when MooseX::Worker::Engine
308             detects that your manager class contains any methods beginning with sig_.
309             Signals are case-sensitive, so if you wish to handle a TERM signal, you must
310             define a sig_TERM() method. Note also that this action is performed upon
311             MooseX::Worker::Engine startup, so any run-time modification of your class
312             which 'does' MooseX::Workers is not likely to be detected.
313              
314             See the sig_TERM handler in the SYNOPSIS for an example.
315              
316             =back
317              
318             =back
319              
320             See L<MooseX::Workers::Engine> for more details.
321             Also see L<MooseX::Workers::Job> if you'd like to give your tasks
322             names, or set timeouts on them.
323              
324              
325             =head1 CONFIGURATION AND ENVIRONMENT
326              
327             MooseX::Workers requires no configuration files or environment variables.
328              
329             =head1 DEPENDENCIES
330              
331             Moose, POE, POE::Wheel::Run
332              
333             =head1 INCOMPATIBILITIES
334              
335             None reported.
336              
337             =head1 BUGS AND LIMITATIONS
338              
339             No bugs have been reported.
340              
341             Please report any bugs or feature requests to
342             C<bug-moosex-workers@rt.cpan.org>, or through the web interface at
343             L<http://rt.cpan.org>.
344              
345              
346             =head1 AUTHORS
347              
348             Chris Prather C<< <perigrin@cpan.org> >>
349              
350             Tom Lanyon C<< <dec@cpan.org> >>
351              
352             Jay Hannah C<< <jay@jays.net> >>
353              
354             Justin Hunter C<< <justin.d.hunter@gmail.com> >>
355              
356             David K. Storrs C<< <david.storrs@gmail.com> >>
357              
358              
359             =head1 LICENCE AND COPYRIGHT
360              
361             Copyright (c) 2007-2010, Chris Prather C<< <perigrin@cpan.org> >>. Some rights reserved.
362              
363             This module is free software; you can redistribute it and/or
364             modify it under the same terms as Perl itself. See L<perlartistic>.
365              
366              
367             =head1 DISCLAIMER OF WARRANTY
368              
369             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
370             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
371             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
372             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
373             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
374             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
375             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
376             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
377             NECESSARY SERVICING, REPAIR, OR CORRECTION.
378              
379             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
380             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
381             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
382             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
383             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
384             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
385             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
386             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
387             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
388             SUCH DAMAGES.
389              
390             =cut
391              
392             1;
393              
394