File Coverage

blib/lib/Mojolicious/Plugin/Minion/Workers.pm
Criterion Covered Total %
statement 3 61 4.9
branch 0 30 0.0
condition 0 28 0.0
subroutine 1 11 9.0
pod 2 7 28.5
total 6 137 4.3


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Minion::Workers;
2 1     1   65991 use Mojo::Base 'Mojolicious::Plugin::Minion';
  1         188768  
  1         8  
3              
4             our $VERSION = '0.9092';# as to Minion version/10+
5              
6             has minion => undef, weak=>1;
7             has qw(conf);
8              
9             sub register {
10 0     0 1   my ($self, $app, $conf) = @_;
11              
12 0           my $workers = delete $conf->{workers};
13 0           my $manage = delete $conf->{manage};
14 0   0       my $tasks = delete $conf->{tasks} || {};
15            
16 0 0         my $backend = (keys %$conf)[0]
17             if keys %$conf == 1;
18            
19             $conf->{$backend} = $conf->{$backend}->($app)
20 0 0 0       if $backend && ref($conf->{$backend}) eq 'CODE';
21              
22 0 0 0       $self->SUPER::register($app, $conf)
23             unless $app->renderer->get_helper('minion') || !$backend;
24              
25 0           $self->minion($app->minion);
26             $self->conf({
27             %$conf,
28             workers => $workers,
29             is_manage => !$ARGV[0]
30             || $ARGV[0] eq 'daemon'
31             || $ARGV[0] eq 'prefork',
32             is_prefork => $ENV{HYPNOTOAD_APP}
33 0   0       || ($ARGV[0] && $ARGV[0] eq 'prefork'),
      0        
34             });
35              
36 0     0     $app->minion->attr('workers'=> sub { $self }, weak=>1);
  0            
37            
38 0           while (my ($name, $sub) = each %$tasks) {
39 0           $app->log->debug(sprintf("Applied task [%s] in [%s] from config", $name, $app->minion->add_task($name => $sub)));
40             }
41            
42             $self->manage()
43 0 0 0       and $self->conf->{is_manage} = 0
44             if $manage;
45              
46 0           return $self;
47             }
48              
49             sub manage {
50 0     0 1   my ($self, $workers) = @_;
51 0           my $conf = $self->conf;
52             return
53 0 0         unless $conf->{is_manage};
54              
55             $workers ||= $conf->{workers}
56 0 0 0       or return;
57              
58 0           my $minion = $self->minion;
59              
60 0 0         if ($conf->{is_prefork}) {
61 0           $self->prefork;
62             } else {
63 0           $self->subprocess;
64             }
65 0           return $self;
66             }
67              
68             # Cases: hypnotoad script/app.pl | perl script/app.pl prefork
69             sub prefork {
70 0     0 0   my ($self) = @_;
71            
72             # case hot deploy and kill -USR2
73             return
74             #~ if $hypnotoad_pid && !$ENV{HYPNOTOAD_STOP};
75 0 0 0       if $ENV{HYPNOTOAD_PID} && !$ENV{HYPNOTOAD_STOP};
76              
77 0           $self->kill_workers;
78            
79 0 0         return if $ENV{HYPNOTOAD_STOP};
80              
81 0           my $workers = $self->conf->{workers};
82 0           while ($workers--) {
83 0 0         defined(my $pid = fork())
84             || die "Can't fork: $!";
85 0 0         next if $pid;
86 0           daemonize();
87 0           $self->worker_run;
88 0           CORE::exit(0);
89             }
90             }
91              
92             # Cases: morbo script/app.pl | perl script/app.pl daemon
93             sub subprocess {
94 0     0 0   my ($self) = @_;
95              
96 0           $self->kill_workers;
97              
98             # subprocess allow run/restart worker later inside app worker
99 0           my $subprocess = Mojo::IOLoop::Subprocess->new();
100             $subprocess->run(
101             sub {
102 0     0     my $subprocess = shift;
103 0           $self->worker_run;
104 0           return $$;
105             },
106 0     0     sub {1}
107 0           );
108             # Dont $subprocess->ioloop->start here!
109             }
110              
111             sub worker_run {
112 0     0 0   my ($self) = @_;
113 0           my $minion = $self->minion;
114 0           $ENV{MINION_PID} = $$;
115 0           $0 = "$0 minion worker";
116 0           $minion->app->log->info("Minion worker (pid $$) was starting");
117 0           $minion->worker->run;
118             }
119              
120              
121              
122             sub kill_workers {
123 0     0 0   my ($self, $workers) = @_;
124 0           my $minion = $self->minion;
125 0   0       $workers ||= $minion->backend->list_workers->{workers};
126              
127             kill 'QUIT', $_->{pid}
128             and $minion->app->log->info("Minion worker (pid $_->{pid}) was stopped")
129 0   0       for @$workers;
130             }
131              
132             sub daemonize {
133             #~ chdir("/") || die "can't chdir to /: $!";
134             #~ defined(my $pid = fork()) || die "can't fork: $!";
135             #~ return 0
136             #~ if $pid; # parent
137            
138 0     0 0   require POSIX;
139 0 0         (POSIX::setsid() != -1) || die "Can't start a new session: $!";
140 0 0         open(STDIN, "< /dev/null") || die "Can't read /dev/null: $!";
141 0 0         open(STDOUT, "> /dev/null") || die "Can't write to /dev/null: $!";
142 0 0         open(STDERR, ">&STDOUT") || die "Can't dup stdout: $!";
143              
144             #~ return $$;
145             }
146              
147             1;
148              
149             __END__