PHPackages                             ipl/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. ipl/scheduler

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

ipl/scheduler
=============

Icinga PHP Library - Tasks scheduler

v0.3.0(3mo ago)129.6k↑384.4%1[5 PRs](https://github.com/Icinga/ipl-scheduler/pulls)1MITPHPPHP &gt;=8.2CI passing

Since Jan 10Pushed yesterday9 watchersCompare

[ Source](https://github.com/Icinga/ipl-scheduler)[ Packagist](https://packagist.org/packages/ipl/scheduler)[ Docs](https://github.com/Icinga/ipl-scheduler)[ RSS](/packages/ipl-scheduler/feed)WikiDiscussions main Synced yesterday

READMEChangelog (5)Dependencies (16)Versions (19)Used By (1)

Icinga PHP Library - Tasks Scheduler
====================================

[](#icinga-php-library---tasks-scheduler)

`ipl-scheduler` provides an event-loop-driven task scheduler for PHP. It runs tasks at regular intervals or once at a specific time, using an event-driven and promise-based model built on top of [ReactPHP](https://reactphp.org/).

Tasks are plain PHP classes. Frequency is configured independently via cron expressions, one-off datetimes, or iCalendar recurrence rules. The scheduler emits lifecycle events so you can observe scheduling, execution, completion, failures, and expiration without coupling your tasks to the scheduler itself.

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

[](#installation)

The recommended way to install this library is via [Composer](https://getcomposer.org):

```
composer require ipl/scheduler
```

`ipl/scheduler` requires PHP 8.2 or later.

For production use, install the [`ext-ev`](https://www.php.net/manual/en/intro.ev.php)PHP extension to improve event loop efficiency.

Key Abstractions
----------------

[](#key-abstractions)

ClassDescription`Scheduler`Manages tasks in the ReactPHP event loop`Cron`Repeating frequency driven by a cron expression`RRule`Repeating frequency driven by an iCalendar RRULE`OneOff`Single-run frequency at an exact point in timeUsage
-----

[](#usage)

### Implementing a Task

[](#implementing-a-task)

Implement the `Task` interface. Use the `TaskProperties` trait to satisfy the `getName()`, `getUuid()`, and `getDescription()` requirements without boilerplate.

Return `resolve()` or `reject()` when the result is already available synchronously. For background work such as async I/O, subprocess calls, or non-blocking HTTP requests, use a `Deferred` and settle it once the operation finishes:

```
use ipl\Scheduler\Common\TaskProperties;
use ipl\Scheduler\Contract\Task;
use Ramsey\Uuid\Uuid;
use React\EventLoop\Loop;
use React\Promise\Deferred;
use React\Promise\PromiseInterface;
use Throwable;

use function React\Promise\resolve;

class SendReport implements Task
{
    use TaskProperties;

    public function __construct()
    {
        $this->setName('send-report');
        $this->setUuid(Uuid::uuid4());
    }

    public function run(): PromiseInterface
    {
        // Use resolve()/reject() only when the result is already available synchronously.
        // return resolve('Report sent.');

        // Use a Deferred when the work happens asynchronously, e.g. after a
        // subprocess call, a stream read, or a non-blocking HTTP call completes.
        $deferred = new Deferred();

        Loop::futureTick(function () use ($deferred): void {
            try {
                // Perform actual work here.
                $deferred->resolve('Report sent.');
            } catch (Throwable $e) {
                $deferred->reject($e);
            }
        });

        return $deferred->promise();
    }
}
```

> **Note:** Always call either `resolve()` or `reject()` on every code path. A `Deferred` whose promise is never settled will silently prevent `ON_TASK_DONE` and `ON_TASK_FAILED` from firing.

### Scheduling with a Cron Expression

[](#scheduling-with-a-cron-expression)

Use `Cron` to run a task on a repeating schedule defined by a standard five-field cron expression:

```
use ipl\Scheduler\Cron;
use ipl\Scheduler\Scheduler;
use React\EventLoop\Loop;

$scheduler = new Scheduler();

// Run every day at 08:00.
$scheduler->schedule(new SendReport(), new Cron('0 8 * * *'));

Loop::run();
```

### Scheduling a One-Off Run

[](#scheduling-a-one-off-run)

Use `OneOff` to run a task exactly once at a specific datetime:

```
use ipl\Scheduler\OneOff;
use ipl\Scheduler\Scheduler;
use React\EventLoop\Loop;

$scheduler = new Scheduler();

$scheduler->schedule(new SendReport(), new OneOff(new DateTime('2026-04-01 09:00:00')));

Loop::run();
```

### Scheduling with an iCalendar Recurrence Rule

[](#scheduling-with-an-icalendar-recurrence-rule)

Use `RRule` for complex recurrence patterns. Pass a timezone string to align recurrences with a specific offset:

```
use ipl\Scheduler\RRule;
use ipl\Scheduler\Scheduler;
use React\EventLoop\Loop;

$scheduler = new Scheduler();

// Run every day at 09:00 Europe/Berlin time.
$frequency = RRule::fromFrequency(RRule::DAILY);
$frequency
    ->setTimezone('Europe/Berlin')
    ->startAt(new DateTime('2026-01-01 09:00:00'));

$scheduler->schedule(new SendReport(), $frequency);

Loop::run();
```

You can also construct an `RRule` directly from an RRULE string:

```
$frequency = new RRule('FREQ=WEEKLY;BYDAY=MO,WE,FR');
```

### Listening to Lifecycle Events

[](#listening-to-lifecycle-events)

The scheduler emits events at each stage of a task's lifecycle. Register listeners using `on()`:

```
use ipl\Scheduler\Scheduler;
use ipl\Scheduler\Contract\Task;
use React\Promise\PromiseInterface;

$scheduler = new Scheduler();

$scheduler->on(Scheduler::ON_TASK_SCHEDULED, function (Task $task, DateTime $runAt) {
    echo sprintf('Task "%s" scheduled for %s', $task->getName(), $runAt->format('c'));
});

$scheduler->on(Scheduler::ON_TASK_RUN, function (Task $task, PromiseInterface $promise) {
    echo sprintf('Task "%s" is running', $task->getName());
});

$scheduler->on(Scheduler::ON_TASK_DONE, function (Task $task, mixed $result) {
    echo sprintf('Task "%s" completed: %s', $task->getName(), $result);
});

$scheduler->on(Scheduler::ON_TASK_FAILED, function (Task $task, Throwable $e) {
    echo sprintf('Task "%s" failed: %s', $task->getName(), $e->getMessage());
});

$scheduler->on(Scheduler::ON_TASK_EXPIRED, function (Task $task, DateTime $expiredAt) {
    echo sprintf('Task "%s" expired at %s', $task->getName(), $expiredAt->format('c'));
});
```

#### Available Events

[](#available-events)

ConstantTriggered when`Scheduler::ON_TASK_SCHEDULED`An operation is queued for future execution`Scheduler::ON_TASK_RUN`An operation starts running`Scheduler::ON_TASK_DONE`An operation completes successfully`Scheduler::ON_TASK_FAILED`An operation throws or rejects`Scheduler::ON_TASK_EXPIRED`A task has passed its configured end time`Scheduler::ON_TASK_CANCEL`A task is removed while an operation is pending### Removing a Task

[](#removing-a-task)

Call `remove()` to cancel a scheduled task at any time. Any pending operations are canceled and the `ON_TASK_CANCEL` event is emitted:

```
$scheduler->remove($task);
```

To remove all scheduled tasks at once:

```
$scheduler->removeTasks();
```

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for a list of notable changes.

License
-------

[](#license)

`ipl/scheduler` is licensed under the terms of the [MIT License](LICENSE.md).

###  Health Score

52

—

FairBetter than 96% of packages

Maintenance92

Actively maintained with recent releases

Popularity29

Limited adoption so far

Community24

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~275 days

Total

5

Last Release

100d ago

PHP version history (2 changes)v0.1.0PHP &gt;=7.2

v0.2.0PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/39625a91c802211110651e31881abdd47b715dad6a8879493d55933eb24a46c0?d=identicon)[ipl](/maintainers/ipl)

---

Top Contributors

[![yhabteab](https://avatars.githubusercontent.com/u/57616252?v=4)](https://github.com/yhabteab "yhabteab (73 commits)")[![lippserd](https://avatars.githubusercontent.com/u/1894563?v=4)](https://github.com/lippserd "lippserd (53 commits)")[![nilmerg](https://avatars.githubusercontent.com/u/16668527?v=4)](https://github.com/nilmerg "nilmerg (12 commits)")[![jrauh01](https://avatars.githubusercontent.com/u/81301701?v=4)](https://github.com/jrauh01 "jrauh01 (10 commits)")[![sukhwinder33445](https://avatars.githubusercontent.com/u/54990055?v=4)](https://github.com/sukhwinder33445 "sukhwinder33445 (9 commits)")[![Jan-Schuppik](https://avatars.githubusercontent.com/u/114286749?v=4)](https://github.com/Jan-Schuppik "Jan-Schuppik (2 commits)")

---

Tags

schedulerjobcrontask

### Embed Badge

![Health badge](/badges/ipl-scheduler/health.svg)

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

###  Alternatives

[laravel/framework

The Laravel Framework.

34.8k543.8M20.1k](/packages/laravel-framework)[shopware/platform

The Shopware e-commerce core

3.4k1.5M3](/packages/shopware-platform)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M574](/packages/shopware-core)[crunzphp/crunz

Schedule your tasks right from the code.

2332.4M7](/packages/crunzphp-crunz)[orisai/scheduler

Cron job scheduler - with locks, parallelism and more

4044.1k5](/packages/orisai-scheduler)[rector/rector-src

Instant Upgrade and Automated Refactoring of any PHP code

136406.3k14](/packages/rector-rector-src)

PHPackages © 2026

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