PHPackages                             oat-sa/job-scheduler - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. oat-sa/job-scheduler

ActiveLibrary[Queues &amp; Workers](/categories/queues)

oat-sa/job-scheduler
====================

PHP job scheduler

v0.1.1(2mo ago)0167↓50%1MITPHPPHP &gt;=8.1CI failing

Since Feb 20Pushed 2mo agoCompare

[ Source](https://github.com/oat-sa/job-scheduler)[ Packagist](https://packagist.org/packages/oat-sa/job-scheduler)[ Docs](https://github.com/oat-sa/job-scheduler)[ RSS](/packages/oat-sa-job-scheduler/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (6)Versions (4)Used By (1)

job-scheduler
=============

[](#job-scheduler)

[![Latest Version on Packagist](https://camo.githubusercontent.com/64961ec727f6074f3933d93121b34b43f845a4b241decf2ca230ac073c37bd78/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6875746e696b61752f6a6f622d7363686564756c65722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/hutnikau/job-scheduler)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)[![Build Status](https://camo.githubusercontent.com/a221089be71518bbcac96ab0490ce33d85682199c165487179fd6031841494f2/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f6875746e696b61752f6a6f622d7363686564756c65722f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/hutnikau/job-scheduler)[![Coverage Status](https://camo.githubusercontent.com/9404c10420925ae149f9d50f027b2c613a072b2adc71e9d15ad26acd00596071/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f636f7665726167652f672f6875746e696b61752f6a6f622d7363686564756c65722e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/hutnikau/job-scheduler/code-structure)[![Quality Score](https://camo.githubusercontent.com/1b474959f93ec69b4082dd56c467c5867cf89faee483e83e36e7f65da3eb5455/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f6875746e696b61752f6a6f622d7363686564756c65722e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/hutnikau/job-scheduler)[![Total Downloads](https://camo.githubusercontent.com/08329edab461a9660f6837519e859cf45fa72dfa1b29669d664dbfdc533bacdd/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6875746e696b61752f6a6f622d7363686564756c65722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/hutnikau/job-scheduler)

Job scheduler is a PHP library for scheduling time-based repetitive actions. It uses ([RRULE](https://tools.ietf.org/html/rfc5545)) or Cron notation to configure time and recurrence rule of each job.

Goals
-----

[](#goals)

Sometimes amount of cron jobs becomes too large. The main goal is reduce amount of cron jobs to only one.

Installation
------------

[](#installation)

Via Composer

```
$ composer require hutnikau/job-scheduler
```

Usage
-----

[](#usage)

### Create recurrence rule

[](#create-recurrence-rule)

iCalendar syntax

```
$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 syntax:

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

### Get the recurrences between dates

[](#get-the-recurrences-between-dates)

```
$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'
```

### Get the next recurrence after given date

[](#get-the-next-recurrence-after-given-date)

```
$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')
```

### Create a job

[](#create-a-job)

Job constructor have the following signature: `\Scheduler\Job\Job::__construct(RRule $rRule, callable $callable);`

Example: iCalendar syntax

```
$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 syntax:

```
$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
});
```

> Note: Cron syntax does not allow to limit number of occurrences.

Create Job from string using iCalendar syntax:

```
$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
);
```

Create Job from string using cron syntax:

```
$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
);
```

### Schedule a job

[](#schedule-a-job)

Scheduler constructor accepts array of jobs as first parameter:

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

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

### Run scheduled jobs

[](#run-scheduled-jobs)

Run all jobs scheduled from '2017-12-12 20:00:00' to '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);
```

> Note: the last `true` parameter means that jobs scheduled exactly at `from` or `to` time will be included. In this example it means that jobs scheduled to be run at '2017-12-12 20:00:00' or '2017-12-12 20:10:00' will be executed.

`$jobRunner->run(...)` returns an array of reports (\\Scheduler\\Action\\Report)

### Workers

[](#workers)

Worker is supposed to be run continuously and check with defined period if there are jobs to be executed.

```
$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');
```

Worker above will make two iterations (checks if there is a job to execute) with an interval of one minute. Default amount of iterations is 1000.

### Action inspectors

[](#action-inspectors)

In order to be able to run two or more workers on different servers or to avoid execution of one job twice action inspectors may be used:

```
$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);
```

Currently there is also Rds implementation so all the performed actions data can be stored in SQL storage. Constructor of expects to receive `\Doctrine\DBAL\Connection` instance:

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

> Note: Make sure you prepared the database (created the table) using initDb static method:

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

### Reports

[](#reports)

`\Scheduler\Action\Report` class synopsis:

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

```

In case if during execution an exception has been thrown then this exception will be returned as a result of action.

`$report->getType()` returns one of two values: `\Scheduler\Action\Report::TYPE_SUCCESS | \Scheduler\Action\Report::TYPE_ERROR`

Warnings
--------

[](#warnings)

1. Be careful with timezones. Make sure that you create `\DateTime` instances with correct timezone.
2. Accuracy of scheduler up to seconds. You must be accurate with `$from`, `$to` parameters passed to the runner to not miss an action or not launch an action twice (alternatively use action inspectors).
3. Use `\Scheduler\Job\CronRule` implementation in case if number of occurrences is not limited.
4. `\Scheduler\Job\RRule` implementation is more flexible but in case of large or unlimited number of repeats there may be performance issues. By default limit of `\Scheduler\Job\RRule` implementation is 732 repeats. More information:

Testing
-------

[](#testing)

```
$ composer test
```

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- This library was created by [Aleh Hutnikau](https://github.com/hutnikau)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance85

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 Bus Factor1

Top contributor holds 70% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

80d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/98ddc6f1b615b1fac2d59f1e72d5dc6056cf6650414271da90cb3f0e203516fe?d=identicon)[bugalood](/maintainers/bugalood)

![](https://www.gravatar.com/avatar/c0ec704e0a8abaf0c27b227ad05d7aca23bc8f83d195229d94d4508cddc0fd24?d=identicon)[oat-lionel](/maintainers/oat-lionel)

![](https://www.gravatar.com/avatar/723a1fd1ece5276155af140d62801e89884eaf8663b643d3a0fb826e49e9ec6b?d=identicon)[jsconan](/maintainers/jsconan)

---

Top Contributors

[![tikhanovichA](https://avatars.githubusercontent.com/u/1053022?v=4)](https://github.com/tikhanovichA "tikhanovichA (7 commits)")[![damner](https://avatars.githubusercontent.com/u/346802?v=4)](https://github.com/damner "damner (1 commits)")[![jbout](https://avatars.githubusercontent.com/u/5815304?v=4)](https://github.com/jbout "jbout (1 commits)")[![tarampampam](https://avatars.githubusercontent.com/u/7326800?v=4)](https://github.com/tarampampam "tarampampam (1 commits)")

---

Tags

scheduler

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/oat-sa-job-scheduler/health.svg)

```
[![Health](https://phpackages.com/badges/oat-sa-job-scheduler/health.svg)](https://phpackages.com/packages/oat-sa-job-scheduler)
```

###  Alternatives

[revolt/event-loop

Rock-solid event loop for concurrent PHP applications.

91943.6M138](/packages/revolt-event-loop)[hutnikau/job-scheduler

PHP job scheduler

7989.4k](/packages/hutnikau-job-scheduler)[contributte/scheduler

PHP job scheduler (cron) with locking

31835.3k1](/packages/contributte-scheduler)[orisai/scheduler

Cron job scheduler - with locks, parallelism and more

4037.1k4](/packages/orisai-scheduler)[matviib/scheduler

Service for scheduling and managing cron tasks in laravel application

213.3k](/packages/matviib-scheduler)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
