Scheduler

A schedule

The Scheduler runs repeated jobs without an extra daemon. A job is a small message object, and a schedule maps each message to a rhythm like every hour or every Monday. The block below is the whole shape: one schedule plus one recurring message.

use Symfony\Component\Scheduler\RecurringMessage; use Symfony\Component\Scheduler\Schedule; $schedule = new Schedule(); $schedule->add(RecurringMessage::every("1 hour", new CleanupMessage()));

Add messages

Each job is a plain PHP object that carries the job settings, and a handler does the work when the message arrives. Keep messages tiny: data in, no services inside, so they stay easy to store and retry.

class CleanupMessage { public function __construct(public readonly int $olderThanDays = 30) { } } class CleanupHandler { public function __invoke(CleanupMessage $message): void { // delete rows older than $message->olderThanDays } }

Run it

Schedules travel through Messenger, so a worker process executes the jobs. Start a worker that listens on the scheduler transport and watch the first run in the terminal before wiring any cron line.

$ php bin/console messenger:consume scheduler_default -vv

Handled 1 message from scheduler_default

One cron line

The worker exits after its time limit, so one cron line restarts it every minute. That single line is the full production setup for small projects: cron wakes the worker, the worker runs due messages, then it exits.

* * * * * cd /var/www/app && php bin/console messenger:consume scheduler_default --time-limit=60

Empty output: cron restarts the worker each minute

Next: Webhooks

Article author: Arthur Isaev