File Coverage

blib/lib/Mojolicious/Plugin/Parallol.pm
Criterion Covered Total %
statement 46 54 85.1
branch 20 26 76.9
condition 6 7 85.7
subroutine 7 7 100.0
pod 1 1 100.0
total 80 95 84.2


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Parallol;
2              
3 1     1   1232 use Mojo::Base 'Mojolicious::Plugin';
  1         2  
  1         9  
4 1     1   225 use Scalar::Util 'weaken';
  1         2  
  1         69  
5 1     1   26 use Carp;
  1         3  
  1         706  
6              
7             sub register {
8 1     1 1 105 my ($plugin, $app) = @_;
9              
10             $app->helper(on_parallol => sub {
11 10     10   15723 my $p = shift->stash('parallol');
12 10 50       395 carp "Can't call on_parallol outside of Parallol" unless $p;
13              
14             # Setter.
15 10 100       47 return $p->{done} = shift if @_;
16              
17             # Getter w/ default.
18             return $p->{done} ||= sub {
19 2         4 my $self = shift;
20 2 100       6 $self->render unless $self->stash('mojo.finished');
21             }
22 1   100     10 });
  6         64  
23              
24             $app->hook(around_dispatch => sub {
25 12     12   455759 my ($next, $self) = @_;
26              
27 12         34 my $p = {};
28 12         74 $self->stash(parallol => $p);
29              
30             # This number represents the number of pending calls (that is, calls
31             # that have been done, but the callback hasn't been called yet).
32             # Every time this number gets decremented to zero, you must also
33             # call $self->on_parallol->($self) to signal that everything is
34             # done.
35             #
36             # This number starts at 1 because we consider the action itself a
37             # pending call.
38 12         225 $p->{paralloling} = 1;
39              
40             # Call action.
41 12         35 $next->();
42              
43             # If the action didn't call $self->parallol, don't do anything more.
44 12 100       272591 return unless $p->{paralloled};
45              
46             # The action is now done. As mentioned above, we must call
47             # on_parallol if there's nothing left to do.
48 6 100       25 return $self->on_parallol->($self) if --$p->{paralloling} == 0;
49              
50             # If the IO loop is not running ...
51 5 50       22 return if Mojo::IOLoop->is_running;
52              
53             # ... we want to run the IO loop and stop it again when it's done.
54 0         0 my $cb = $self->on_parallol;
55             $self->on_parallol(sub {
56             # Run the callback; capture any errors.
57 0 0       0 eval { $cb->(@_); 1 } or my $e = $@;
  0         0  
  0         0  
58 0         0 Mojo::IOLoop->stop;
59             # Re-throw the error.
60 0 0       0 die $e if $e;
61 0         0 });
62            
63 0         0 Mojo::IOLoop->start;
64 1         106 });
65            
66             $app->helper(
67             parallol => sub {
68 10     10   7476 my $callback = pop;
69 10         33 my ($self, %opts) = @_;
70 10         34 my $p = $self->stash('parallol');
71              
72 10 100 66     154 if (ref $callback && ref $callback eq 'CODE') {
73 4 100 100     31 weaken($self) if $opts{weaken} // 1;
74             } else {
75 6         13 my $name = $callback;
76 6         105 $callback = sub { $self->stash($name => pop) }
77 6         38 }
78              
79             # Mark the request as async and paralloled.
80 10         46 $self->render_later;
81 10         175 $p->{paralloled} = 1;
82              
83             # Increment pending calls.
84 10         20 $p->{paralloling}++;
85              
86              
87             sub {
88             # Run the callback.
89 10 100       601051 eval { $callback->(@_); 1 } or $self->render_exception($@);
  10         46  
  9         546  
90              
91             # Run on_parallol if it's finished.
92 10 100       87832 if (--$p->{paralloling} == 0) {
93 5 100       11 eval { $self->on_parallol->($self); 1 } or $self->render_exception($@);
  5         64  
  4         14111  
94             }
95             }
96 10         104 }
97 1         47 );
98             }
99              
100             "Parallolololololololololol";
101              
102             __END__