hutnikau/job-scheduler

PHP任务调度器

v0.6.1 2019-04-18 09:42 UTC

This package is not auto-updated.

Last update: 2024-09-15 04:31:31 UTC


README

Latest Version on Packagist Software License Build Status Coverage Status Quality Score Total Downloads

任务调度器是一个PHP库,用于调度基于时间的重复操作。它使用RRULE或Cron表示法来配置每个任务的执行时间和重复规则。

目标

有时cron任务的量变得过大。主要目标是减少cron任务的量,只保留一个。

安装

通过Composer

$ composer require hutnikau/job-scheduler

用法

创建重复规则

iCalendar语法

$executionTime = new \DateTime('2017-12-12 20:00:00');
//run monthly, at 20:00:00, 5 times
$rule          = new \Scheduler\Job\RRule('FREQ=MONTHLY;COUNT=5', $executionTime);

Cron语法

$executionTime = new \DateTime('2017-12-12 20:00:00');
//run monthly, at 20:00:00
$rule          = new \Scheduler\Job\CronRule('0 20 * 1 *', $executionTime);

获取日期之间的重复项

$dt = new DateTime('2017-12-28T21:00:00');
$dtPlusFiveMinutes = new DateTime('2017-12-28T21:05:00');
$rRule = new CronRule('* * * * *', $dt); //minutely
$rRule->getRecurrences($dt, $dtPlusFiveMinutes); //array with six DateTime instances from '2017-12-28T21:00:00' to '2017-12-28T21:05:00'

获取给定日期之后的下一个重复项

$dt = new DateTime('2017-12-28T21:00:00');
$rRule = new CronRule('* * * * *', $dt); //minutely
$rRule->getNextRecurrence($dt); //DateTime instance ('2017-12-28T21:00:00')
//not including given date
$rRule->getNextRecurrence($dt, false); //DateTime instance ('2017-12-28T21:01:00')

创建一个任务

任务的构造函数具有以下签名:\Scheduler\Job\Job::__construct(RRule $rRule, callable $callable);

示例:iCalendar语法

$executionTime = new \DateTime('2017-12-12 20:00:00');
//run monthly, at 20:00:00, 5 times
$rule          = new \Scheduler\Job\RRule('FREQ=MONTHLY;COUNT=5', $executionTime);
$job           = new \Scheduler\Job\Job($rule, function () {
    //do something
});

Cron语法

$executionTime = new \DateTime('2017-12-12 20:00:00');
//run monthly, at 20:00:00
$rule          = new \Scheduler\Job\CronRule('0 20 * 1 *', $executionTime);
$job           = new \Scheduler\Job\Job($rule, function () {
    //do something
});

注意:Cron语法不允许限制重复次数。

使用iCalendar语法从字符串创建任务

$job = \Scheduler\Job\Job::createFromString(
    'FREQ=MONTHLY;COUNT=5', //Recurrence rule 
    '2017-12-28T21:00:00',  //Start date
    function() {},          //Callback
    'Europe/Minsk'          //Tmezone. If $timezone is omitted, the current timezone will be used
);

使用cron语法从字符串创建任务

$job = \Scheduler\Job\Job::createFromString(
    '0 0 1 * *',            //Cron syntax recurrence rule 
    '2017-12-28T21:00:00',  //Start date
    function() {},          //Callback
    'Europe/Minsk'          //Tmezone. If $timezone is omitted, the current timezone will be used
);

调度任务

调度器构造函数接受一个包含任务的数组作为第一个参数

$scheduler = new \Scheduler\Scheduler([
    $job,
    //more jobs here
]);

//also you may add jobs by `\Scheduler\Scheduler::addJob($job)`
$scheduler->addJob($anotherJob);

运行计划中的任务

运行从'2017-12-12 20:00:00'到'2017-12-12 20:10:00'计划的所有任务

$jobRunner = new \Scheduler\JobRunner\JobRunner();
$from      = new \DateTime('2017-12-12 20:00:00');
$to        = new \DateTime('2017-12-12 20:10:00');
$reports   = $jobRunner->run($scheduler, $from, $to, true);

注意:最后一个true参数表示如果任务计划在fromto时间执行,则将包含这些任务。在本例中,这意味着计划在'2017-12-12 20:00:00'或'2017-12-12 20:10:00'执行的任务将被执行。

$jobRunner->run(...)返回一个报告数组(\Scheduler\Action\Report)

工作进程

工作进程应持续运行并检查是否需要执行任务。

$jobRunner = new \Scheduler\JobRunner\JobRunner();
$scheduler = new \Scheduler\Scheduler([
    $job,
    //more jobs here
]);
$worker = new \Scheduler\Worker\Worker($jobRunner, $scheduler);
$worker->setMaxIterations(2);
$worker->run(time(), 'PT1M');

上述工作进程将以一分钟为间隔进行两次迭代(检查是否有要执行的任务)。默认的迭代次数为1000。

操作检查器

为了能够在不同的服务器上运行两个或更多的工作进程或避免重复执行一个任务,可以使用操作检查器

$actionInspector = new \Scheduler\ActionInspector\FileActionInspector('pathToFile');
$jobRunner       = new \Scheduler\JobRunner\JobRunner($actionInspector);
$from            = new \DateTime('2017-12-12 20:00:00');
$to              = new \DateTime('2017-12-12 20:10:00');
$reports         = $jobRunner->run($scheduler, $from, $to, true);

//call of `run` action with the same parameters will not execute any jobs because they already logged by inspecor as finished
//$reports array is empty
$reports         = $jobRunner->run($scheduler, $from, $to, true);

目前也存在Rds实现,因此所有执行的操作数据都可以存储在SQL存储中。构造函数期望接收\Doctrine\DBAL\Connection实例

    $actionInspector = new \Scheduler\ActionInspector\RdsActionInspector($connection);

注意:请确保使用initDb静态方法准备了数据库(创建了表)

    \Scheduler\ActionInspector\RdsActionInspector::initDb($connection);

报告

\Scheduler\Action\Report类概要

\Scheduler\Action\Report {
    /* Methods */
    public mixed getReport ( void )
    public mixed getAction ( void )
    public mixed getType ( void )
}

如果在执行期间抛出异常,则此异常将作为操作的结果返回。

$report->getType()返回两个值之一:\Scheduler\Action\Report::TYPE_SUCCESS | \Scheduler\Action\Report::TYPE_ERROR

警告

  1. 请小心处理时区。请确保使用正确的时区创建\DateTime实例。
  2. 调度器的准确性达到秒。你必须确保传递给运行器的$from$to参数的准确性,以避免错过操作或重复执行操作(或者使用操作检查器)。
  3. 如果重复次数不受限制,请使用\Scheduler\Job\CronRule实现。
  4. \Scheduler\Job\RRule实现更灵活,但在重复次数多或无限的情况下可能会出现性能问题。默认情况下,\Scheduler\Job\RRule实现的限制为732次重复。更多信息:[https://github.com/simshaun/recurr](https://github.com/simshaun/recurr)

测试

$ composer test

安全性

如果您发现任何与安全相关的问题,请通过电子邮件goodnickoff@gmail.com联系,而不是使用问题跟踪器。

致谢

许可协议

麻省理工学院许可证(MIT)。有关更多信息,请参阅许可文件