Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re^2: singleton lock not reliable

by cavac (Parson)
on Jun 25, 2021 at 12:20 UTC ( [id://11134272]=note: print w/replies, xml ) Need Help??


in reply to Re: singleton lock not reliable
in thread singleton lock not reliable

crontab? File locks? docker???

Writing a simple cyclic thingy isn't that hard. Let's say you have a program that calculates the meaning of life, the universe and everything. It takes a varying time to execute. You want to call it every ten seconds or so, except when it takes longer to run. First, we need the program:

#!/usr/bin/env perl use strict; use warnings; sleep(int(rand(10) + 5)); print "42\n";

Then we write a cyclic executive that keeps track of the run time of the external program (=the scheduler):

#!/usr/bin/env perl use strict; use warnings; use Time::HiRes qw(time sleep); my $cmd = "./meaningoflifetheuniverseandeverything.pl"; my $cycletime = 10; while(1) { my $starttime = time; `$cmd`; my $endtime = time; my $timetaken = $endtime - $starttime; if($timetaken >= $cycletime) { print "Immediate restart\n"; next; } my $sleeptime = $cycletime - $timetaken; print "Sleeping for $sleeptime\n"; sleep($sleeptime); }

This effectively implements a simple "minimum cycle time" scheduler:

Sleeping for 0.986798048019409 Sleeping for 4.98646092414856 Sleeping for 3.98296499252319 Immediate restart Immediate restart Immediate restart Immediate restart

If you want a more crontab like behaviour with start times aligned to specific times, you can use take the current time, calculate the modulos (division remainder) for the cycle time. Then calculate difference between that and a full cycle time interval how long to sleep. Like this:

#!/usr/bin/env perl use strict; use warnings; use Time::HiRes qw(time sleep); my $cmd = "./meaningoflifetheuniverseandeverything.pl"; my $cycletime = 10; while(1) { my $endtime = time; my $sleeptime = $cycletime - ($endtime % $cycletime) - 1; if($sleeptime) { print "Sleeping for $sleeptime\n"; sleep($sleeptime); } `$cmd`; }

Result:

Sleeping for 9 Sleeping for 5 Sleeping for 9 Sleeping for 6 Sleeping for 6 Sleeping for 7

This has a jitter of up to one second, but that should be acceptable enough, i think. Depending on your required time zone settings, you also might have to tweak the whole thing by about 37 seconds, plus/minus a couple of leap seconds every few years, something like this:

my $TAIoffset = -37; ... my $endtime = time + $TAIoffset;

But that's probably overkill for most purposes.

perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'

Replies are listed 'Best First'.
Re^3: singleton lock not reliable
by choroba (Cardinal) on Jun 25, 2021 at 14:23 UTC
    > Writing a simple cyclic thingy isn't that hard.

    One of the advantages of cron is it's restarted when the machine is restarted or when it crashes for whatever reason. Instead of trying to achieve the same with a cyclic thingy, I'd rather go with crontab.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      Good point. I was mostly trying to point out that using a complicated solution like Docker is a bit much for such a simple problem.

      perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11134272]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2024-04-25 10:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found