File Coverage

blib/lib/Mojolicious/Plugin/Subprocess.pm
Criterion Covered Total %
statement 28 28 100.0
branch 4 6 66.6
condition 1 2 50.0
subroutine 5 5 100.0
pod 1 1 100.0
total 39 42 92.8


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Subprocess;
2              
3 1     1   745 use Mojo::Base 'Mojolicious::Plugin';
  1         2  
  1         9  
4 1     1   302 use Mojo::IOLoop;
  1         3  
  1         11  
5 1     1   33 use Mojo::Promise;
  1         3  
  1         10  
6              
7             our $VERSION = '1.001';
8              
9             sub register {
10 1     1 1 49 my ($self, $app, $options) = @_;
11            
12 1   50     3 my %subprocess_args = %{$options // {}};
  1         17  
13 1         3 my $use_sereal = delete $subprocess_args{use_sereal};
14            
15             $app->helper(subprocess => sub {
16 3     3   100930 my ($c, $child, $parent) = @_;
17            
18 3         22 my $subprocess = Mojo::IOLoop->subprocess;
19 3         155 $subprocess->$_($subprocess_args{$_}) for
20 9         38 grep { exists $subprocess_args{$_} } qw(deserialize ioloop serialize);
21 3 50       16 $subprocess->with_roles('Mojo::IOLoop::Subprocess::Role::Sereal')
22             ->with_sereal if $use_sereal;
23              
24 3         16 my $tx = $c->render_later->tx;
25              
26 3         130 my $p = Mojo::Promise->new;
27             $subprocess->run($child, sub {
28 3         19927 my ($subprocess, $err, @results) = @_;
29 3 100       52 return $p->reject($err) if $err;
30 2         25 $p->resolve(@results);
31 3         64 });
32              
33 2         759 return $p->then(sub { $c->$parent(@_) })
34 3 50       10678 ->catch(sub { $c->helpers->reply->exception(pop) and undef $tx });
  2         1183  
35 1         23 });
36             }
37              
38             1;
39              
40             =head1 NAME
41              
42             Mojolicious::Plugin::Subprocess - Subprocesses in Mojolicious applications
43              
44             =head1 SYNOPSIS
45              
46             use Mojolicious::Lite;
47            
48             plugin 'Subprocess';
49            
50             get '/slow' => sub {
51             my $c = shift;
52             $c->subprocess(sub {
53             return do_slow_stuff();
54             }, sub {
55             my ($c, @results) = @_;
56             $c->render(json => \@results);
57             });
58             };
59            
60             # or use Sereal as serializer
61             plugin 'Subprocess' => {use_sereal => 1};
62              
63             =head1 DESCRIPTION
64              
65             L is a L plugin that adds a
66             L helper method to your application, which uses
67             L to perform computationally expensive operations in
68             subprocesses without blocking the event loop.
69              
70             The option C (requires L)
71             will use L for data serialization, which is faster than L and
72             supports serialization of more reference types such as C. The
73             L is supported to control
74             serialization of blessed objects.
75              
76             Any other options passed to the plugin will be used as attributes to build the
77             L object.
78              
79             Note that it does not increase the timeout of the connection, so if your forked
80             process is going to take a very long time, you might need to increase that
81             using L.
82              
83             =head1 HELPERS
84              
85             L implements the following helpers.
86              
87             =head2 subprocess
88              
89             $c->subprocess(sub {
90             my $subprocess = shift;
91             ...
92             }, sub {
93             my ($c, @results) = @_;
94             ...
95             });
96              
97             Execute the first callback in a child process with
98             L, and execute the second callback in the
99             parent process with the results. Automatic rendering is disabled, and an
100             exception response is rendered if an exception is thrown in either callback.
101             This also means that the parent callback will not be called if an exception is
102             thrown in the child callback.
103              
104             =head1 METHODS
105              
106             L inherits all methods from
107             L and implements the following new ones.
108              
109             =head2 register
110              
111             $plugin->register(Mojolicious->new);
112             $plugin->register(Mojolicious->new, {ioloop => $ioloop});
113              
114             Register helper in L application.
115              
116             =head1 BUGS
117              
118             Report any issues on the public bugtracker.
119              
120             =head1 AUTHOR
121              
122             Dan Book
123              
124             =head1 COPYRIGHT AND LICENSE
125              
126             This software is Copyright (c) 2016 by Dan Book.
127              
128             This is free software, licensed under:
129              
130             The Artistic License 2.0 (GPL Compatible)
131              
132             =head1 SEE ALSO
133              
134             L, L