Scheduled Jobs with Custom Clock Processes
With custom clock processes, you have the ability to specify custom schedule. You will also have other benefits like environment parity between development and production, or time precision in your task scheduling.
Definition of the Custom Clock Process
The implementation of the custom clock will vary depending on the used language. However, defining the clock process is standard and is done in the Procfile
.
Example
Here is an example of the process definition using the Ruby library clockwork
:
web: bundle exec puma -C config/puma.rb
clock: bundle exec clockwork clock.rb
Start the Task Scheduler
Once your application has been deployed, scale your ‘clock’ to 1 to start the task scheduler:
$ scalingo --app my-app scale clock:1
Implementation Examples
Ruby
In Ruby you can use clockwork, resque-scheduler or sidekiq-scheduler (Sidekiq Enterprise has cron-like feature built-in) for example.
Example With the Clockwork Gem
Initialization is done in the file clock.rb
and a new kind of container must be defined in the
Procfile
of the project, the container type clock
:
clock: bundle exec clockwork clock.rb
The file which implements the cron-like process is defined in clock.rb
:
require 'clockwork'
require 'active_support/time' # Allow numeric durations (eg: 1.minutes)
module Clockwork
handler do |job|
puts "Running #{job}"
end
# handler receives the time when job is prepared to run in the 2nd argument
# handler do |job, time|
# puts "Running #{job}, at #{time}"
# end
every(10.seconds, 'frequent.job')
every(3.minutes, 'less.frequent.job')
every(1.hour, 'hourly.job')
every(1.day, 'midnight.job', :at => '00:00')
end
For more information about using clockwork
, please refer to the official clockwork page.
PHP
With PHP, you can use the package cron/cron, otherwise each framework has its own task scheduler. You may want to use:
Example
A complete example project can be found here.
It uses the package cron/cron
to implement the tasks scheduler.
Its initialization is done in the file cron.php
and a new kind of container is defined in the
Procfile
of the project, the container type clock
:
clock: php cron.php
The file which implements the cron-like process is defined in cron.php
:
<?php
require(__DIR__ . '/vendor/autoload.php');
echo "[CRON] Starting tasks scheduler\n";
function build_cron() {
// Increment redis key every minute
$inc_job = new \Cron\Job\ShellJob();
$inc_job->setCommand('php inc.php');
$inc_job->setSchedule(new \Cron\Schedule\CrontabSchedule('*/2 * * * *'));
$resolver = new \Cron\Resolver\ArrayResolver();
$resolver->addJob($inc_job);
$cron = new \Cron\Cron();
$cron->setExecutor(new \Cron\Executor\Executor());
$cron->setResolver($resolver);
return $cron;
}
$cron = build_cron();
// Every 60 seconds, run the scheduler which will execute the tasks
// which have to be started at the given minute.
while(true) {
echo "[CRON] Running tasks\n";
$report = $cron->run();
while ($cron->isRunning()) { }
echo "[CRON] " . count($report->getReports()) . " tasks have been executed\n";
foreach($report->getReports() as $job_report) {
$output = $job_report->getOutput();
foreach($output as $line) {
echo "[CRON] " . $line;
}
}
sleep(60);
}
?>
Node.js
In Node.js you can use different package such as node-cron or node-schedule.
Example
The following example uses the node-cron
package.
Its initialization is done in the file cron.js
and a new kind of container must be defined in the
Procfile
of the project, the container type clock
:
clock: node cron.js
The file which implements the cron-like process is defined in cron.js
:
var cron = require('cron');
var job1 = new cron.CronJob({
cronTime: '*/2 * * * *',
onTick: function() {
now = new Date();
console.log(now + ': job 1 ticked');
},
start: true,
timeZone: 'Europe/Paris'
});
var job2 = new cron.CronJob({
cronTime: '* * * * *',
onTick: function() {
now = new Date();
console.log(now + ': job 2 ticked');
},
start: true,
timeZone: 'Europe/Paris'
});
console.log('Started 2 cron jobs')
With this example, the job1
ticks every 2 minutes and the job2
ticks every minute. Each job
displays a message in the log of the application.
The code is available in sample-node-express.