elektro-potkan / scheduler
Robust job scheduler (cron) with locking
Requires
- php: >= 7.2
- dragonmantank/cron-expression: ^3.0.1
- nette/safe-stream: ^2.4
- nette/utils: ^3.0.1
Requires (Dev)
- phpstan/phpstan: ^0.12
- phpstan/phpstan-deprecation-rules: ^0.12
- phpstan/phpstan-nette: ^0.12
- phpstan/phpstan-strict-rules: ^0.12
- tracy/tracy: ^2.3
Suggests
- elektro-potkan/scheduler-console: to use scheduler from console
- elektro-potkan/scheduler-di: to integrate with Nette DI
README
Simplifies running periodic jobs of PHP application. Just register all of them to the scheduler and let it to run them at specified time by single call.
Heavily modified fork of contributte/scheduler.
Original package reorganised - jobs moved into individual namespace as well as schedulers.
Console and Nette DI integrations split into separate packages.
Run composer suggests
for more info.
Usage
The bundled jobs are using the cron syntax.
Example
// init
$scheduler = new ElektroPotkan\Scheduler\Schedulers\LastCheck('path-to-directory-for-storing-locks-and-timestamp');
$scheduler->add(new ElektroPotkan\Scheduler\Jobs\Callback('0 3 * * *',// daily at 3:00 a.m.
function(): void {
do_something();
}
));
// run periodically - optimaly each minute, but heavily depends on Your needs and configured jobs
$scheduler->run();
Cron syntax
See description below. You can also validate your cron using crontab.guru.
* * * * *
- - - - -
| | | | |
| | | | |
| | | | +----- day of week (0 - 7) (Sunday=0 or 7)
| | | +---------- month (1 - 12)
| | +--------------- day of month (1 - 31)
| +-------------------- hour (0 - 23)
+------------------------- min (0 - 59)
Schedulers
All the schedulers provided in this package are in the namespace ElektroPotkan\Scheduler\Schedulers
.
A list of the available schedulers - the next one is extending the previous one, so it also provides all features of all previous ones.
Simple
- The most basic implementation of scheduler.
- Does not need any storage.
- If not called each minute, the job's requested run times might be missed.
- No locking is provided when running the jobs so if called concurrently, the jobs will be also run concurrently.
Locking
- Uses locks when running the jobs, so if called concurrently, it will skip the job if it is already being run by another instance.
- Needs directory to store locks.
LastCheck
- Provides
$lastCheck
timestamp to jobs. - If not called each minute, the jobs might use such information to be run at the next call. Eliminates the problem of missing the jobs run times even if not called at their exact time. All jobs provided by this package supports this feature.
- Provides
LastRun
- Most advanced type of scheduler, provides each job with its
$lastRun
timestamp. - Feature not used by the jobs provided by this package as they do not need it.
- Most advanced type of scheduler, provides each job with its
Jobs
This package provides 2 basic jobs (located in the namespace ElektroPotkan\Scheduler\Jobs
):
Callback
- Runs given callback.AExpression
- Abstract class providing cron syntax support.
Callback job
If You need to call a method myClassMethod
of Your class instance $myClass
, simply use Callback
job:
// run each minute by cron syntax
$job = new ElektroPotkan\Scheduler\Jobs\Callback('* * * * *', [$myClass, 'myClassMethod']);
$scheduler->add($job);
Custom cron-syntax job
To get more flexibility for Your job but use cron syntax effortlessly, extend the AExpression
job:
class MyCronJob extends ElektroPotkan\Scheduler\Jobs\AExpression {
private $myDataSource;
public function __construct(string $cron, $myDataSource){
parent::__construct($cron);
$this->myDataSource = $myDataSource;
}
public function run(): void {
$this->myDataSource->runSomePeriodicTask();
}
}
$job = new MyCronJob('0 0 * * 1', $myDataSource);// run each Monday at midnight
$scheduler->add($job);
Custom job
For full freedom with Your job, just implement the ElektroPotkan\Scheduler\IJob
interface:
class MyJob implements ElektroPotkan\Scheduler\IJob {
private $dateService;
private $statisticsService;
public function __construct($dateService, $statisticsService){
$this->dateService = $dateService;
$this->statisticsService = $statisticsService;
}
public function isDue(
DateTimeInterface $now,
?DateTimeInterface $lastCheck = null,
?DateTimeInterface $lastRun = null
): bool {
return $this->dateService->isRightTime($now);
}
public function run(): void {
$this->statisticsService->calculate();
}
}
Logging
To log info and errors from built-in schedulers,
You need to provide an implementation of ElektroPotkan\Scheduler\ILogger
interface via setLogger
call:
// $logger implements ElektroPotkan\Scheduler\ILogger
$scheduler->setLogger($logger);
If You are using Tracy
, You can use the provided TracyLogger
:
// $logger implements Tracy\ILogger
$scheduler->setLogger(new ElektroPotkan\Scheduler\TracyLogger($logger));
Authors
- Modified fork by Elektro-potkan git@elektro-potkan.cz.
- Original Contributte package authors (see Composer config file):
Info
Versioning
This project uses Semantic Versioning 2.0.0 (semver.org).
Branching
This project uses slightly modified Git-Flow Workflow and Branching Model:
- https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
- https://nvie.com/posts/a-successful-git-branching-model/
License
You may use this program under the terms of the MIT License.
See file LICENSE.