Cataly...heduler(3pm)

πŸ“¦
version 0.10 Β· 3 versions
, in debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

✨ Catalyst::Plugin::Scheduler β€” aka the cron-vibes plugin πŸ’…

okay bestie, welcome to Catalyst::Plugin::Scheduler, a User Contributed Perl Documentation page (yes, it's a 3pm manpage, very demure, very mindful) and it's literally the plugin that lets your Catalyst app run events on a cron-style schedule. Let's get into it 🫢


🌸 NAME

Catalyst::Plugin::Scheduler β€” schedule events to run in a cron-like fashion. no cap, that's the whole point.


πŸ¦‹ SYNOPSIS

use Catalyst qw/Scheduler/;

# run remove_sessions in the Cron controller every hour
__PACKAGE__->schedule(
    at    => '0 * * * *',
    event => '/cron/remove_sessions'
);

# Run a subroutine at 4:05am every Sunday
__PACKAGE__->schedule(
    at    => '5 4 * * sun',
    event => \&do_stuff,
);

# A long-running scheduled event that must be triggered
# manually by an authorized user
__PACKAGE__->schedule(
    trigger => 'rebuild_search_index',
    event   => '/cron/rebuild_search_index',
);

and then you just hit it like this:

$ wget -q http://www.myapp.com/?schedule_trigger=rebuild_search_index

πŸ’– DESCRIPTION

so this plugin lets you schedule events to run at recurring intervals, like a lil alarm clock for your app ⏰

here's the tea tho: events run during the first request that meets or exceeds the specified time. so depending on how much traffic your app gets, events might run exactly on time, or they might run a lil late. it's giving "close enough" β€” but honestly it's plenty to satisfy a lot of basic scheduling needs. periodt.


πŸŽ€ CONFIGURATION

configuration is optional and it lives in MyApp->config->{scheduler}.

🌈 logging

set this to 1 and you get logging of events as they get executed. this option is enabled by default when running under -Debug mode. and btw, errors are always logged no matter what this option is set to β€” that part is non-negotiable πŸ’€

🌸 time_zone

the time zone of your system. it gets autodetected where possible, and defaults to UTC (GMT) if it can't figure it out. wanna override it? just hand it a valid DateTime time zone string, like 'America/New_York'. iconic.

πŸ¦‹ state_file

the current state of every event is stored in a file. by default that's $APP_HOME/scheduler.state. this file gets created on the first request if it doesn't already exist. ✨

🧚 yaml_file

the location of the optional YAML event configuration file. by default it's $APP_HOME/scheduler.yml.

πŸ’œ hosts_allow

this one specifies IP addresses for trusted users. it defaults to 127.0.0.1. you can specify multiple addresses by passing an array reference. and heads up: this option is used for both events where auto_run is set to 0 and for manually-triggered events. so it's doing double duty, main character energy fr.

__PACKAGE__->config->{scheduler}->{hosts_allow} = '192.168.1.1';
__PACKAGE__->config->{scheduler}->{hosts_allow} = [
    '127.0.0.1',
    '192.168.1.1'
];

⭐ SCHEDULING

πŸ• AUTOMATED EVENTS

events get scheduled by calling the class method schedule.

MyApp->schedule(
    at       => '0 * * * *',
    event    => '/cron/remove_sessions',
);

package MyApp::Controller::Cron;

sub remove_sessions : Private {
    my ( $self, $c ) = @_;

    $c->delete_expired_sessions;
}

πŸŒ™ at

the time to run an event is specified using crontab(5)-style syntax.

5 0 * * *      # 5 minutes after midnight, every day
15 14 1 * *    # run at 2:15pm on the first of every month
0 22 * * 1-5   # run at 10 pm on weekdays
5 4 * * sun    # run at 4:05am every Sunday

straight from crontab(5):

field          allowed values
-----          --------------
minute         0-59
hour           0-23
day of month   1-31
month          0-12 (or names, see below)
day of week    0-7 (0 or 7 is Sun, or use names)

and instead of the first five fields, one of these seven special strings can show up:

string         meaning
------         -------
@yearly        Run once a year, "0 0 1 1 *".
@annually      (same as @yearly)
@monthly       Run once a month, "0 0 1 * *".
@weekly        Run once a week, "0 0 * * 0".
@daily         Run once a day, "0 0 * * *".
@midnight      (same as @daily)
@hourly        Run once an hour, "0 * * * *".

πŸ¦‹ event

the event to run at the specified time can be either a Catalyst private action path or a coderef. both types of event methods receive the $c object from the current request β€” but bestie, listen: you must not rely on any request-specific info present in $c, because it'll be from a random user request at or near the event's specified run time. it's a vibe, not a guarantee 😭

Important: methods used for events should be marked Private so they can't be executed via the browser. protect your app, queen.

πŸ‘‘ auto_run

the auto_run parameter specifies when the event is allowed to be executed. by default it's set to 1, so the event runs during the first request that matches the specified time in at.

if you set it to 0, the event will only run when a request is made by a user from an authorized address. the whole purpose of this option is to let long-running tasks execute only for certain users.

MyApp->schedule(
    at       => '0 0 * * *',
    event    => '/cron/rebuild_search_index',
    auto_run => 0,
);

package MyApp::Controller::Cron;

sub rebuild_search_index : Private {
    my ( $self, $c ) = @_;

    # rebuild the search index, this may take a long time
}

so now the search index only gets rebuilt when a request comes in from a user whose IP address matches the list in the hosts_allow config option. and to actually run this event, you probably wanna ping the app from a cron job:

0 0 * * * wget -q http://www.myapp.com/

πŸ’… MANUAL EVENTS

wanna create an event that does not run on a set schedule and has to be manually triggered? easy. just specify the trigger option instead of at.

__PACKAGE__->schedule(
    trigger => 'send_email',
    event   => '/events/send_email',
);

then you trigger it with a standard web request from an authorized user. the trigger to run is specified using a special GET parameter, 'schedule_trigger' β€” and the path requested literally does not matter. slay.

http://www.myapp.com/?schedule_trigger=send_email

by default, manual events may only be triggered by requests made from localhost (127.0.0.1). to let other addresses run events, use the config option hosts_allow.


🌈 SCHEDULING USING A YAML FILE

as an alternative to the schedule() method, you can define scheduled events in an external YAML file. by default the plugin looks for a file called scheduler.yml in your application's home directory. wanna change the filename? use the config option yaml_file. πŸ’«

modifications to this file get re-read once per minute during the normal event checking process. cute.

here's an example YAML config file with 4 events. each event is denoted with a '-' character, followed by the same parameters used by the schedule method. and important: coderef events are not supported by the YAML file. noted πŸ“

---
- at: '* * * * *'
  event: /cron/delete_sessions
- event: /cron/send_email
  trigger: send_email
- at: '@hourly'
  event: /cron/hourly
- at: 0 0 * * *
  auto_run: 0
  event: /cron/rebuild_search_index

πŸ›‘οΈ SECURITY

all events run inside of an eval container. this protects you from receiving any error messages or page crashes if an event fails to run properly. and all event errors are logged, even if logging is disabled. no silent failures here, we don't do that πŸ’…


🫢 PLUGIN SUPPORT

other plugins may register scheduled events if they need to do periodic maintenance. plugin authors, be sure to inform your users if you do this! and events should be registered from a plugin's setup method.

sub setup {
    my $c = shift;
    $c->maybe::next::method(@_);

    if ( $c->can('schedule') ) {
        $c->schedule(
            at    => '0 * * * *',
            event => \&cleanup,
        );
    }
}

πŸ’€ CAVEATS

the time at which an event runs is determined completely by the requests made to the application. apps with heavy traffic may have events run very close to the correct time, while apps with low traffic may see events running much later than scheduled. if that's a problem for you, use a real cron entry that just hits your app at the desired time:

0 * * * * wget -q http://www.myapp.com/

and also: events that consume a lot of time will slow down request processing for the user who triggers the event. for those types of events, you should use auto_run => 0 or manual event triggering. protect the user's experience bestie πŸ™ˆ


⚑ PERFORMANCE

the plugin only checks once per minute to see if any events need to run, so the overhead on each request is minimal. on the author's test server, the difference between running with Scheduler and without was only around 0.02% (0.004 seconds). that's basically nothing, we love to see it πŸ”₯

of course, when a scheduled event actually runs, performance will depend on what's being run in the event. obviously.


πŸŽ€ METHODS

🌸 schedule

schedule is a class method for adding scheduled events. see the SCHEDULING section for more info. (the original page phrases it as "SCHEDULING"" in " β€” some formatting gremlin energy, but you get it.)

πŸ¦‹ scheduler_state

the current state of all scheduled events is available in an easy-to-use format by calling $c->scheduler_state. you can use this data to build an admin view into the scheduling engine, for example. this same data is also displayed on the Catalyst debug screen. obsessed.

this method returns an array reference containing a hash reference for each event.

[
    {
        'last_run'    => '2005-12-29 16:29:33 EST',
        'auto_run'    => 1,
        'last_output' => 1,
        'at'          => '0 0 * * *',
        'next_run'    => '2005-12-30 00:00:00 EST',
        'event'       => '/cron/session_cleanup'
    },
    {
        'auto_run'    => 1,
        'at'          => '0 0 * * *',
        'next_run'    => '2005-12-30 00:00:00 EST',
        'event'       => '/cron/build_rss'
    },
]

πŸ’œ INTERNAL METHODS

these are the methods this plugin extends.

  • dispatch β€” the main scheduling logic takes place during the dispatch phase.
  • dump_these β€” on the Catalyst debug screen, all scheduled events are displayed along with the next time they'll be executed.
  • setup

πŸ‘€ SEE ALSO

crontab(5) β€” go read it, iykyk πŸ“–


✍️ AUTHOR

Andy Grundman, <andy@hybridized.org>


this program is free software, you can redistribute it and/or modify it under the same terms as Perl itself.


and that's a wrap bestie!! πŸŽ€ this lil doc came to you from perl v5.38.2, dated 2024-03-04, and it's the Catalyst::Plugin::Scheduler page, section 3pm. go schedule something iconic πŸ’…βœ¨

πŸ“¦ where this page comes from