start recurring timer once with multiple workers

136 views
Skip to first unread message

Tim

unread,
Jul 3, 2014, 5:46:10 AM7/3/14
to mojol...@googlegroups.com
Hi,

is it possible to start a recurring timer only once when I have multiple workers?

So that I get this output

$ perl test.pl prefork -w 1
[Thu Jul  3 11:29:09 2014] [info] Listening at "http://*:3000".
Server available at http://127.0.0.1:3000.
[Thu Jul  3 11:29:09 2014] [info] Manager 1836 started.
[Thu Jul  3 11:29:09 2014] [debug] Worker 1837 started.
[Thu Jul  3 11:29:12 2014] [info] 0
[Thu Jul  3 11:29:15 2014] [info] 1
[Thu Jul  3 11:29:18 2014] [info] 2

instead of

$ perl test.pl prefork -w 4
[Thu Jul  3 11:29:28 2014] [info] Listening at "http://*:3000".
Server available at http://127.0.0.1:3000.
[Thu Jul  3 11:29:28 2014] [info] Manager 1838 started.
[Thu Jul  3 11:29:28 2014] [debug] Worker 1839 started.
[Thu Jul  3 11:29:28 2014] [debug] Worker 1840 started.
[Thu Jul  3 11:29:28 2014] [debug] Worker 1841 started.
[Thu Jul  3 11:29:28 2014] [debug] Worker 1842 started.
[Thu Jul  3 11:29:31 2014] [info] 0
[Thu Jul  3 11:29:32 2014] [info] 0
[Thu Jul  3 11:29:32 2014] [info] 0
[Thu Jul  3 11:29:32 2014] [info] 0
[Thu Jul  3 11:29:34 2014] [info] 1
[Thu Jul  3 11:29:35 2014] [info] 1
[Thu Jul  3 11:29:35 2014] [info] 1
[Thu Jul  3 11:29:35 2014] [info] 1
[Thu Jul  3 11:29:37 2014] [info] 2
[Thu Jul  3 11:29:38 2014] [info] 2
[Thu Jul  3 11:29:38 2014] [info] 2
[Thu Jul  3 11:29:38 2014] [info] 2

Code

use Mojolicious::Lite;

get '/' => sub {
    my $c = shift;
    $c->render(text => 'test');
};

sub start_recurring {
    my $i;

    Mojo::IOLoop->recurring(3 => sub {
      app->log->info($i++);
    });
}

start_recurring;

app->start;

Stefan Adams

unread,
Jul 3, 2014, 8:22:51 AM7/3/14
to mojolicious

On Thu, Jul 3, 2014 at 4:46 AM, Tim <ta1...@safe-mail.net> wrote:
is it possible to start a recurring timer only once when I have multiple workers?

I think I've seen a similar discussion in this forum before, but I can't find it.  IIRC, the final consensus was that for the requested behavior, the developer should be calling recurring from a Mojolicious::Command and execute it from the command line or cron and not calling this "maintenance code" from a Controller where its execution is dependent on a connecting client.

Sorry if I'm wrong.  HTH!

Jan Henning Thorsen

unread,
Jul 3, 2014, 8:44:15 AM7/3/14
to mojol...@googlegroups.com
Could you rather explain what the actual problem that you're trying to solve is?

Maybe the answer is a cron-job :)

I've implemented some really awful locking mechanism in Convos to only start a piece of code in one child. It creates a lock in the Redis database to prevent the other children from running the same code. https://metacpan.org/source/JHTHORSEN/Convos-0.6/lib/Convos.pm#L323

What is important is that the lock need to be atomic. symlink() and $handle->open($name, O_CREAT | O_EXCL) and friends are atomic, but you need to be cautious about hypnotoad and "hot reload", or just the fact that the child that started the recurring timer might die. 

Per Carlson

unread,
Jul 3, 2014, 9:10:46 AM7/3/14
to mojolicious
Hi.
This thread might be the one you are thinking of:
https://groups.google.com/forum/#!topic/mojolicious/UK6oHtJBIcQ

Tim

unread,
Jul 7, 2014, 3:48:45 AM7/7/14
to mojol...@googlegroups.com
Thanks, but I want to do it without a cron job in a single Mojolicious::Lite app.

Do you think this is a viable solution?

Mojo::IOLoop->next_tick(sub {
    if(! -e 'timer.running') {
        open my $fh, '>', 'timer.running' or die $!;
        app->log->debug('timer created');

        Mojo::IOLoop->recurring(1 => sub {
            #...
        });
    }
});

Reply all
Reply to author
Forward
0 new messages