Crontab for Perl Mojolicous?

70 Views Asked by At

In a Mojolicous full app, I have a model helper which returns a hash. I would like to update the contents of this hash (from a downloaded CSV) on a regular basis.

My question: is it possible to schedule a function within Mojolicious to update my model on a specified interval?

In the example below, I have 2 routes:

  • GET /update - downloads an updated CSV, and stores it as ${epoch}.json
  • GET / - lists users, by reading the newest ${epoch}.json file and returning the desired hash.
use Mojolicious::Lite -signatures;

helper users => sub($self) {
    my $users;
    my $newest;
    foreach my $filename (sort {$b cmp $a} glob("1*.csv")) {
        $newest = $filename;
        last;
    }
    open my $fh, "<:encoding(utf8)", $newest or die $!;
    while (<$fh>) {
        next if $. == 1; # ignore CSV header
        my ($name,$email,$phone) = split(',');
        $users->{$email} = $name;
    }
    close($fh);
    $users;
};

helper update => sub ($self) {
    my $tx = $self->ua->get( 'https://test-backend.lambdatest.com/api/dev-tools/csv-generator' );
    my $res = eval { $tx->result };
    return $@ if $@;
    my $epoch = Mojo::Date->new()->epoch;
    Mojo::File->new( "${epoch}.csv" )->spurt( $res->text );
    return 'ok';
};

get '/' => sub ($self) {
    my @names = sort values %{ $self->users };
    $self->render(json => {emails=>[@names]} );
    
};

get '/update' => sub ($self) {
    $self->render(text => $self->update );
};

app->start;
1

There are 1 best solutions below

0
Rawley Fowler On

You can use Mojolicious::Plugin::Cron to add Crontab style callbacks to your Mojolicious applications.

use Mojolicious::Lite;

plugin Cron => (
    sched1 => {
        base    => 'utc',
        crontab => '*/30 * * * *', # Run every 30 mins
        code    => sub {
             say "30 minutes!";
        }
    },

    sched2 => {
        base    => 'utc',
        crontab => '0 * * * *', # Run every hour
        code    => sub {
             say "1 hour!";
        }
    }
);

app->start;