#!/usr/bin/env perl use FindBin; use lib "$FindBin::Bin/../lib"; use App::Netdisco; # for netdisco app config use Dancer qw/:moose :script/; # callbacks and local job queue management use App::Netdisco::Daemon::Queue ':all'; use MCE; use Role::Tiny; use Path::Class 'dir'; my $mce = MCE->new( tmp_dir => dir($ENV{HOME}, 'tmp'), spawn_delay => 0.15, job_delay => 0.15, user_func => \&call_worker_body, on_post_exit => \&restart_worker, user_tasks => build_tasks_list(), )->run(); sub call_worker_body { my ($self) = @_; $self->worker_body if $self->can('worker_body'); } sub restart_worker { my ($self, $e) = @_; reset_jobs($e->{wid}); $self->restart_worker($e->{wid}); } sub build_tasks_list { my $tasks = [{ max_workers => 1, user_begin => worker_factory('Manager'), }]; set(daemon_pollers => 2) if !defined setting('daemon_pollers'); set(daemon_interactives => 2) if !defined setting('daemon_interactives'); # XXX MCE does not like max_workers => 0 push @$tasks, { max_workers => setting('daemon_pollers'), user_begin => worker_factory('Poller'), } if setting('daemon_pollers'); push @$tasks, { max_workers => setting('daemon_interactives'), user_begin => worker_factory('Interactive'), } if setting('daemon_interactives'); return $tasks; } sub worker_factory { my $role = shift; return sub { my $self = shift; # with "App::Netdisco::Daemon::Worker::$role"; $self->worker_begin if $self->can('worker_begin'); }; } __END__ sub register_worker { my (undef, $pid) = @_; $workers{$pid} = $next_role; } sub unregister_worker { my (undef, $pid, $status) = @_; delete $workers{$pid}; # also check for bad exit status? # revert any running jobs (will be such if child died) try { schema('daemon')->resultset('Admin') ->search({status => "running-$pid"}) ->update({status => 'queued', started => undef}); } catch { warn "error reverting jobs for pid $pid: $_\n" }; }