our
$VERSION
=
'0.9091'
;
has
minion
=>
undef
,
weak
=>1;
has
qw(conf)
;
sub
register {
my
(
$self
,
$app
,
$conf
) =
@_
;
my
$workers
=
delete
$conf
->{workers};
my
$manage
=
delete
$conf
->{manage};
my
$tasks
=
delete
$conf
->{tasks} || {};
my
$backend
= (
keys
%$conf
)[0]
if
keys
%$conf
== 1;
$conf
->{
$backend
} =
$conf
->{
$backend
}->(
$app
)
if
$backend
&&
ref
(
$conf
->{
$backend
}) eq
'CODE'
;
$self
->SUPER::register(
$app
,
$conf
)
unless
$app
->renderer->get_helper(
'minion'
) || !
$backend
;
$self
->minion(
$app
->minion);
$self
->conf({
%$conf
,
workers
=>
$workers
,
is_manage
=> !
$ARGV
[0]
||
$ARGV
[0] eq
'daemon'
||
$ARGV
[0] eq
'prefork'
,
is_prefork
=>
$ENV
{HYPNOTOAD_APP}
|| (
$ARGV
[0] &&
$ARGV
[0] eq
'prefork'
),
});
$app
->minion->attr(
'workers'
=>
sub
{
$self
},
weak
=>1);
while
(
my
(
$name
,
$sub
) =
each
%$tasks
) {
$app
->
log
->debug(
sprintf
(
"Applied task [%s] in [%s] from config"
,
$name
,
$app
->minion->add_task(
$name
=>
$sub
)));
}
$self
->manage()
and
$self
->conf->{is_manage} = 0
if
$manage
;
return
$self
;
}
sub
manage {
my
(
$self
,
$workers
) =
@_
;
my
$conf
=
$self
->conf;
return
unless
$conf
->{is_manage};
$workers
||=
$conf
->{workers}
or
return
;
my
$minion
=
$self
->minion;
if
(
$conf
->{is_prefork}) {
$self
->prefork;
}
else
{
$self
->subprocess;
}
return
$self
;
}
sub
prefork {
my
(
$self
) =
@_
;
return
if
$ENV
{HYPNOTOAD_PID} && !
$ENV
{HYPNOTOAD_STOP};
$self
->kill_workers;
return
if
$ENV
{HYPNOTOAD_STOP};
my
$workers
=
$self
->conf->{workers};
while
(
$workers
--) {
defined
(
my
$pid
=
fork
())
||
die
"Can't fork: $!"
;
next
if
$pid
;
$self
->worker_run;
CORE::
exit
(0);
}
}
sub
subprocess {
my
(
$self
) =
@_
;
$self
->kill_workers;
my
$subprocess
= Mojo::IOLoop::Subprocess->new();
$subprocess
->run(
sub
{
my
$subprocess
=
shift
;
$self
->worker_run;
return
$$;
},
sub
{1}
);
}
sub
worker_run {
my
(
$self
) =
@_
;
my
$minion
=
$self
->minion;
$ENV
{MINION_PID} = $$;
$0 =
"$0 minion worker"
;
$minion
->app->
log
->info(
"Minion worker (pid $$) was starting"
);
$minion
->worker->run;
}
sub
kill_workers {
my
(
$self
,
$workers
) =
@_
;
my
$minion
=
$self
->minion;
$workers
||=
$minion
->backend->list_workers->{workers};
kill
'QUIT'
,
$_
->{pid}
and
$minion
->app->
log
->info(
"Minion worker (pid $_->{pid}) was stopped"
)
for
@$workers
;
}
1;