PHPackages                             nixphp/schedule - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. nixphp/schedule

ActiveNixphp-plugin[Utility &amp; Helpers](/categories/utility)

nixphp/schedule
===============

NixPHP Schedule Plugin for recurring Tasks.

v0.1.0(4mo ago)054MITPHPPHP &gt;=8.3CI passing

Since Dec 30Pushed 3mo agoCompare

[ Source](https://github.com/nixphp/schedule)[ Packagist](https://packagist.org/packages/nixphp/schedule)[ RSS](/packages/nixphp-schedule/feed)WikiDiscussions main Synced 1mo ago

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

[![Logo](https://camo.githubusercontent.com/075b2860e9651b98b8c190a8296595c54cff6900890d9e494f31131145e98a6f/68747470733a2f2f6e69787068702e6769746875622e696f2f646f63732f6173736574732f6e69787068702d6c6f676f2d736d616c6c2d7371756172652e706e67)](https://camo.githubusercontent.com/075b2860e9651b98b8c190a8296595c54cff6900890d9e494f31131145e98a6f/68747470733a2f2f6e69787068702e6769746875622e696f2f646f63732f6173736574732f6e69787068702d6c6f676f2d736d616c6c2d7371756172652e706e67)

[![NixPHP Schedule Plugin](https://github.com/nixphp/schedule/actions/workflows/php.yml/badge.svg)](https://github.com/nixphp/schedule/actions/workflows/php.yml)

[← Back to NixPHP](https://github.com/nixphp/framework)

---

nixphp/schedule
===============

[](#nixphpschedule)

> **Minimalistic scheduling for NixPHP – cron-based, predictable, and queue-aware.**

This plugin provides a lightweight scheduler for recurring tasks using cron expressions. It is designed to work seamlessly with the NixPHP Queue plugin, without introducing hidden magic or unnecessary complexity.

> 🧩 Part of the official NixPHP plugin collection.
> Use it when you want to run recurring jobs reliably – without relying on system cron files or external schedulers.

---

Features
--------

[](#features)

- Cron-based scheduling (`* * * * *` syntax)
- Central scheduler loop (`schedule:ticker`)
- Queue-backed execution (no direct execution in the ticker)
- **Automatic backlog prevention** (latest run wins)
- Persistent scheduler state (prevents duplicate runs)
- No marker interfaces, no job annotations
- Fully deterministic and testable

---

📥 Installation
--------------

[](#-installation)

```
composer require nixphp/schedule
```

The plugin will be autoloaded automatically.

---

Basic idea
----------

[](#basic-idea)

The scheduler **does not execute jobs directly**.

Instead:

1. The scheduler *decides* which jobs are due
2. Due jobs are **queued**
3. Queue workers execute them asynchronously

This keeps scheduling and execution cleanly separated.

---

Defining scheduled jobs
-----------------------

[](#defining-scheduled-jobs)

A scheduled job is a normal queue job that additionally implements `ScheduledJobInterface`:

```
use NixPHP\Schedule\Core\ScheduledJobInterface;
use NixPHP\Queue\QueueJobInterface;

class CleanupTempFiles implements ScheduledJobInterface, QueueJobInterface
{
    public function getCronExpression(): string
    {
        return '0 * * * *'; // every hour
    }

    public function execute(): void
    {
        // cleanup logic
    }
}
```

---

Registering scheduled jobs
--------------------------

[](#registering-scheduled-jobs)

Register scheduled jobs via the `Scheduler`:

```
$scheduler->addScheduledJob(CleanupTempFiles::class);
```

Payloads can be passed as well:

```
$scheduler->addScheduledJob(CleanupTempFiles::class, [
    'path' => '/tmp'
]);
```

---

Running the scheduler
---------------------

[](#running-the-scheduler)

Start the scheduler ticker via CLI:

```
./bin/nix schedule:ticker
```

The ticker:

- checks all registered jobs
- evaluates cron expressions
- queues jobs that are due

It runs continuously and is usually managed by Supervisor or systemd.

---

Backlog handling (important)
----------------------------

[](#backlog-handling-important)

### The problem

[](#the-problem)

If the scheduler runs but queue workers are down, scheduled jobs can pile up. In most cases this is **not desired**: polling, syncing, rebuilding, or checking tasks usually only need to run *once* with the latest state.

### The solution: automatic coalescing

[](#the-solution-automatic-coalescing)

By default, the scheduler **coalesces scheduled jobs**:

> If a job was scheduled multiple times while workers were unavailable, only the **latest execution** is kept in the queue.

This prevents useless backlogs and keeps execution predictable.

### How it works (internally)

[](#how-it-works-internally)

The scheduler assigns a **deterministic job ID** based on:

- job class
- cron expression

This causes older queued runs to be replaced automatically.

No special configuration is required. Queue drivers remain fully generic.

---

Configuration
-------------

[](#configuration)

You can control this behavior via configuration:

```
// app/config.php
return [
    'queue' => [
        // If true (default): only the latest scheduled job is kept
        // If false: every scheduled run is queued and processed
        'coalesce' => true,
    ],
];
```

### When to disable coalescing

[](#when-to-disable-coalescing)

Set `coalesce` to `false` if:

- every scheduled run must be processed (e.g. audits, snapshots)
- time-based effects must not be skipped
- backlog processing is intentional

---

Duplicate execution prevention
------------------------------

[](#duplicate-execution-prevention)

The scheduler also tracks its own state internally to ensure that:

- a job is only queued **once per cron minute**
- restarts do not cause duplicate enqueues

State is stored in a small JSON file (configurable).

---

Worker interaction
------------------

[](#worker-interaction)

The scheduler **does not spawn queue workers by default**.

You are expected to run queue workers independently, e.g. via Supervisor:

```
./bin/nix queue:worker
```

This keeps the system flexible and avoids hidden background processes.

---

Supervisor example (optional)
-----------------------------

[](#supervisor-example-optional)

```
[program:nixphp-scheduler]
command=php bin/nix schedule:ticker
directory=/path/to/your/app
autostart=true
autorestart=true
stderr_logfile=/var/log/nixphp/scheduler.err.log
stdout_logfile=/var/log/nixphp/scheduler.out.log
```

---

Requirements
------------

[](#requirements)

- `nixphp/framework` ^0.1.0
- `nixphp/queue` ^0.1.0
- `nixphp/cli` ^0.1.0

---

📄 License
---------

[](#-license)

MIT License.

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance79

Regular maintenance activity

Popularity11

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

139d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f5d2bd3eecc9c3949d3caf98c4876c8e44c0c73fc80dbc65b55f4d91a5b63eae?d=identicon)[floknapp](/maintainers/floknapp)

---

Top Contributors

[![FloKnapp](https://avatars.githubusercontent.com/u/3774820?v=4)](https://github.com/FloKnapp "FloKnapp (8 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/nixphp-schedule/health.svg)

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

PHPackages © 2026

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