Download the PHP package faerber/laravel-kernel-cadence without Composer
On this page you can find all versions of the php package faerber/laravel-kernel-cadence. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download faerber/laravel-kernel-cadence
More information about faerber/laravel-kernel-cadence
Files in faerber/laravel-kernel-cadence
Package laravel-kernel-cadence
Short Description Phase-offset sub-hourly cron cadences for the Laravel scheduler. Stop stacking every-N-minutes tasks on the top of the hour.
License MIT
Homepage https://github.com/benfaerber/laravel-kernel-cadence
Informations about the package laravel-kernel-cadence
Laravel Kernel Cadence
Give your every-N-minutes scheduled tasks an explicit phase, so they stop stacking on the top of the hour.
The problem
Laravel's everyFiveMinutes(), everyTenMinutes(), everyFifteenMinutes() and friends all
phase-lock to minute 0. The hour-based helpers already take an offset — hourlyAt(17),
everySixHours(18), everyTwoHours(25) — but the minute-based ones do not, so the only way to
stagger sub-hourly work is to drop out of the fluent API into raw cron:
That matters because scheduled commands are usually thin dispatchers onto one queue, which fans straight out to every worker and lands on the database at once. Reaching for the default helper silently signs your task up for the :00 stampede.
laravel/framework#59966 proposed adding the
offset parameter upstream and was declined, with the suggestion to release it as a package. This is
that package, grown out of the Cadence class posted in that thread.
Getting started
The service provider is auto-discovered. There is nothing to publish and nothing to configure.
Three ways to phase a task
Pick whichever reads best in your Kernel; they produce identical cron expressions.
1. everyMinutes(), the offset parameter the framework helpers do not take:
2. offsetBy(), re-phasing a framework helper you already wrote:
3. Cadence, when you want the expression itself:
A zero offset fires on exactly the same minutes as the helper it replaces, so switching a task over is not a behaviour change until you pass an offset.
Spreading a fan-out across lanes
When several related tasks share one cadence, let the package place them:
Lanes are guaranteed never to share a minute. When the lane count does not divide the interval the phases round down, since cron cannot resolve finer than a minute.
Guarding the whole schedule
Offsetting one task is easy to remember; keeping the whole Kernel spread out is not. ScheduleLoad
measures how many tasks land on each minute of the hour, so a test or a CI step can fail when one
minute gets overloaded.
As an artisan command
Exits non-zero when any minute exceeds --max, so it works as a CI check with no test to write.
By default only tasks that repeat every hour are counted, since a daily 03:00 report is not part of
the stampede the rest of the day; pass --all to count everything.
As a test
Use ApplicationSchedule::resolve() rather than resolving Schedule from the container yourself.
On Laravel 11 and 12 the schedule lives in a withSchedule() callback that only runs once artisan
starts, so a test that reads the container binding directly measures an empty schedule and
passes without checking anything. ApplicationSchedule starts artisan first, so both the Laravel 10
kernel style and the newer callback style are present. As a backstop, the budget assertions
themselves fail if the schedule they were handed carries no tasks at all.
A failure prints the minute, the count and the whole histogram, so you can see where the room is:
If your Kernel gates tasks behind an environment check or a kill switch, build the schedule the way
production builds it before asserting — the assertions take any Schedule or list of Events.
Directly
What is rejected, and why
Misconfiguration throws at definition time, during deploy, rather than silently never running.
Every exception extends InvalidArgumentException.
| Call | Result |
|---|---|
Cadence::everyMinutes(7) |
InvalidInterval — 7 does not divide 60, so the gap across the top of the hour would be uneven |
Cadence::everyMinutes(60) |
InvalidInterval — use hourlyAt() or everySixHours() for hour-based cadences |
Cadence::everyMinutes(15, offsetBy: 15) |
InvalidOffset — an offset at or beyond the interval is just a different phase of the same cadence |
->everyMinute()->offsetBy(1) |
UnsupportedMinuteField — a task running every minute has no phase |
->cron('55 * * * *')->offsetBy(7) |
InvalidOffset — :62 would move the task into the next hour |
->cron('0-30/5 * * * *')->offsetBy(2) |
UnsupportedMinuteField — that is a window, not a whole-hour cadence, and shifting it would change its meaning |
Cadence::everyFiveMinutes()->spreadAcross(6) |
InvalidSpread — more lanes than minutes would collide |
Migrating from the standalone class
If you copied the Cadence class out of the pull request thread, the only change is that the
factories now return a Cadence rather than a string:
Every interval and offset rule is unchanged, including the exception messages.
Compatibility
PHP 8.2+, Laravel 10, 11 and 12.
The everyMinutes, offsetBy and cadence macros are only registered if Event has no method of
that name. If a future Laravel ships its own, core wins and nothing here shadows it.
Development
License
MIT. See LICENSE.
All versions of laravel-kernel-cadence with dependencies
dragonmantank/cron-expression Version ^3.3
illuminate/console Version ^10.0 || ^11.0 || ^12.0
illuminate/support Version ^10.0 || ^11.0 || ^12.0