add scheduler based on Algorithm::Cron
This commit is contained in:
		| @@ -4,6 +4,7 @@ name     'App-Netdisco'; | ||||
| license  'bsd'; | ||||
| all_from 'lib/App/Netdisco.pm'; | ||||
|   | ||||
| requires 'Algorithm::Cron' => 0; | ||||
| requires 'App::cpanminus' => 0; | ||||
| requires 'App::local::lib::helper' => 0; | ||||
| requires 'DBD::Pg' => 0; | ||||
|   | ||||
| @@ -46,6 +46,8 @@ sub build_tasks_list { | ||||
|     user_begin => worker_factory('Manager'), | ||||
|   }]; | ||||
|  | ||||
|   set(daemon_schedulers => 1) | ||||
|     if !defined setting('daemon_schedulers'); | ||||
|   set(daemon_pollers => 2) | ||||
|     if !defined setting('daemon_pollers'); | ||||
|   set(daemon_interactives => 2) | ||||
| @@ -53,6 +55,11 @@ sub build_tasks_list { | ||||
|  | ||||
|   # 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, { | ||||
|     max_workers => setting('daemon_pollers'), | ||||
|     user_begin => worker_factory('Poller'), | ||||
| @@ -63,8 +70,11 @@ sub build_tasks_list { | ||||
|     user_begin => worker_factory('Interactive'), | ||||
|   } if setting('daemon_interactives'); | ||||
|  | ||||
|   info sprintf "MCE will load %s tasks: 1 Manager, %s Poller, %s Interactive", | ||||
|     (1+ scalar @$tasks), (setting('daemon_pollers') || 0), (setting('daemon_interactives') || 0); | ||||
|   info sprintf "MCE will load %s tasks: 1 Manager, %s Scheduler, %s Poller, %s Interactive", | ||||
|     (1+ scalar @$tasks), | ||||
|     (setting('daemon_schedulers') || 0), | ||||
|     (setting('daemon_pollers') || 0), | ||||
|     (setting('daemon_interactives') || 0); | ||||
|   return $tasks; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										79
									
								
								Netdisco/lib/App/Netdisco/Daemon/Worker/Scheduler.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								Netdisco/lib/App/Netdisco/Daemon/Worker/Scheduler.pm
									
									
									
									
									
										Normal 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; | ||||
| @@ -72,6 +72,7 @@ daemon_sleep_time: 5 | ||||
|  | ||||
| # how many daemon processes | ||||
| # NB one worker will always be a Queue Manager | ||||
| daemon_pollers: 0 | ||||
| daemon_schedulers: 1 | ||||
| daemon_interactives: 2 | ||||
| daemon_pollers: 0 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user