add scheduler based on Algorithm::Cron

This commit is contained in:
Oliver Gorwits
2013-03-24 19:45:24 +00:00
parent 49d136b57a
commit 0acbe8abd3
4 changed files with 94 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ name 'App-Netdisco';
license 'bsd'; license 'bsd';
all_from 'lib/App/Netdisco.pm'; all_from 'lib/App/Netdisco.pm';
requires 'Algorithm::Cron' => 0;
requires 'App::cpanminus' => 0; requires 'App::cpanminus' => 0;
requires 'App::local::lib::helper' => 0; requires 'App::local::lib::helper' => 0;
requires 'DBD::Pg' => 0; requires 'DBD::Pg' => 0;

View File

@@ -46,6 +46,8 @@ sub build_tasks_list {
user_begin => worker_factory('Manager'), user_begin => worker_factory('Manager'),
}]; }];
set(daemon_schedulers => 1)
if !defined setting('daemon_schedulers');
set(daemon_pollers => 2) set(daemon_pollers => 2)
if !defined setting('daemon_pollers'); if !defined setting('daemon_pollers');
set(daemon_interactives => 2) set(daemon_interactives => 2)
@@ -53,6 +55,11 @@ sub build_tasks_list {
# XXX MCE does not like max_workers => 0 # XXX MCE does not like max_workers => 0
push @$tasks, {
max_workers => setting('daemon_schedulers'),
user_begin => worker_factory('Scheduler'),
} if setting('daemon_schedulers');
push @$tasks, { push @$tasks, {
max_workers => setting('daemon_pollers'), max_workers => setting('daemon_pollers'),
user_begin => worker_factory('Poller'), user_begin => worker_factory('Poller'),
@@ -63,8 +70,11 @@ sub build_tasks_list {
user_begin => worker_factory('Interactive'), user_begin => worker_factory('Interactive'),
} if setting('daemon_interactives'); } if setting('daemon_interactives');
info sprintf "MCE will load %s tasks: 1 Manager, %s Poller, %s Interactive", info sprintf "MCE will load %s tasks: 1 Manager, %s Scheduler, %s Poller, %s Interactive",
(1+ scalar @$tasks), (setting('daemon_pollers') || 0), (setting('daemon_interactives') || 0); (1+ scalar @$tasks),
(setting('daemon_schedulers') || 0),
(setting('daemon_pollers') || 0),
(setting('daemon_interactives') || 0);
return $tasks; return $tasks;
} }

View File

@@ -0,0 +1,79 @@
package App::Netdisco::Daemon::Worker::Scheduler;
use Dancer qw/:moose :syntax :script/;
use Dancer::Plugin::DBIC 'schema';
use Algorithm::Cron;
use Try::Tiny;
use Role::Tiny;
use namespace::clean;
my $jobactions = {
map {$_ => undef} qw/
discoverall
refresh
macwalk
arpwalk
nbtwalk
backup
/
};
sub worker_begin {
my $self = shift;
my $wid = $self->wid;
debug "entering Scheduler ($wid) worker_begin()";
foreach my $a (keys %$jobactions) {
next unless setting('job_schedule')
and exists setting('job_schedule')->{$a};
my $config = setting('job_schedule')->{$a};
# accept either single crontab format, or individual time fields
my $cron = Algorithm::Cron->new(@{
ref [] eq ref $config->{when}
? $config->{when}
: [crontab => $config->{when}];
});
$jobactions->{$a} = $config;
$jobactions->{$a}->{when} = $cron;
}
}
sub worker_body {
my $self = shift;
my $wid = $self->wid;
while (1) {
# sleep until some point in the next minute
my $naptime = 60 - (time % 60) + int(rand(45));
debug "scheduler ($wid): sleeping for $naptime seconds";
sleep $naptime;
my $win_start = time - (time % 60);
my $win_end = $win_start + 60;
# if any job is due, add it to the queue
foreach my $a (keys %$jobactions) {
next unless defined $jobactions->{$a};
my $sched = $jobactions->{$a};
if ($sched->{when}->next_time($win_start) < $win_end) {
# queue it!
try {
debug "scheduler ($wid): queueing $a job";
schema('netdisco')->resultset('Admin')->create({
action => $a,
device => ($sched->{device} || undef),
subaction => ($sched->{extra} || undef),
status => 'queued',
});
};
}
}
}
}
1;

View File

@@ -72,6 +72,7 @@ daemon_sleep_time: 5
# how many daemon processes # how many daemon processes
# NB one worker will always be a Queue Manager # NB one worker will always be a Queue Manager
daemon_pollers: 0 daemon_schedulers: 1
daemon_interactives: 2 daemon_interactives: 2
daemon_pollers: 0