Subject: | Timeshift option |
This is not a bug but a enhancement I did for the Schedule::Cron module
to fit my needs :
I needed to add what I called a timeshift to the main cron clock to
shift all scheduled jobs in the future or in the past. I am using
several perl scripts running Schedule::Cron concurrently and using
similar crontabs (each one with different accounts/permissions). That
can make many jobs launched exactly at the same time creating heavy CPU
load. By shifting by some seconds or minutes internal Schedule::Cron
clock I can avoid those massive launches without altering the crontabs.
I added a new option to the object creator :
$cron = new Schedule::Cron($dispatcher, timeshift => $ts);
Default is 0 if option is not provided.
I added a new public method to dynamically change the timeshift :
$cron->set_timeshift($ts)
Modify global time shift for all timetable. The timeshift is subbed from
localtime to calculate next execution time for all scheduled jobs.
ts parameter must be in seconds. Default value is 0. Negative values re
allowed to shift time in the past.
Returns actual timeshift in seconds.
Example:
$cron->set_timeshift(120);
Will delay all jobs 2 minutes in the future.
Bug:
My implementation does not rebuild the job list after changing
dynamically the timeshift. So next job execution is still using the
previous timeshift value.
Roland, you can add it to your code if you want and if you feel that it
does not break the module.
I give you a patch against 1.01_3 to add the timeshift functionnality.
Subject: | cron-timeshift.patch |
--- D:/OSP/lib/Schedule/Cron_1.01_b3.pm ven. 3 juin 2011, 10:09:04
+++ D:/OSP/lib/Schedule/Cron.pm mer. 29 juin 2011, 10:22:39
@@ -363,9 +363,11 @@
die "Dispatcher not a ref to a subroutine" unless ref($dispatcher) eq "CODE";
my $cfg = ref($_[0]) eq "HASH" ? $_[0] : { @_ };
$cfg->{processprefix} = "Schedule::Cron" unless $cfg->{processprefix};
+ my $timeshift = $cfg->{timeshift} || 0;
my $self = {
cfg => $cfg,
dispatcher => $dispatcher,
+ timeshift => $timeshift,
queue => [ ],
map => { }
};
@@ -878,7 +880,7 @@
die "No more jobs to run\n";
}
my ($index,$time) = @{shift @{$self->{queue}}};
- my $now = time;
+ my $now = time + $self->{timeshift};
my $sleep = 0;
if ($time < $now)
{
@@ -917,7 +919,7 @@
} else {
sleep($sleep);
}
- $sleep = $time - time;
+ $sleep = $time - (time + $self->{timeshift});
}
$self->_execute($index,$cfg);
@@ -1162,6 +1164,33 @@
}
}
+=item $cron->set_timeshift($ts)
+
+Modify global time shift for all timetable. The timeshift is subbed from localtime
+to calculate next execution time for all scheduled jobs.
+
+ts parameter must be in seconds. Default value is 0. Negative values are allowed to
+shift time in the past.
+
+Returns actual timeshift in seconds.
+
+Example:
+
+ $cron->set_timeshift(120);
+
+ Will delay all jobs 2 minutes in the future.
+
+=cut
+
+sub set_timeshift
+{
+ my $self = shift;
+ my $value = shift || 0;
+
+ $self->{timeshift} = $value;
+ return $self->{timeshift};
+}
+
# ==================================================
# PRIVATE METHODS:
# ==================================================
@@ -1289,7 +1318,7 @@
my $new_time = $self->get_next_execution_time($entry->{time});
# Check, whether next execution time is *smaller* than the current time.
# This can happen during DST backflip:
- my $now = time;
+ my $now = time + $self->{timeshift};
if ($new_time <= $now) {
dbg "Adjusting time calculation because of DST back flip (new_time - now = ",$new_time - $now,")" if $DEBUG;
# We are adding hours as long as our target time is in the future
@@ -1313,7 +1342,7 @@
my $now = shift;
my $expanded = shift;
- my $offset = ($expanded->[5] ? 1 : 60);
+ my $offset = ($expanded->[5] ? 1 : 60) + $self->{timeshift};
my ($now_sec,$now_min,$now_hour,$now_mday,$now_mon,$now_wday,$now_year) =
(localtime($now+$offset))[0,1,2,3,4,6,5];
$now_mon++;