[Messenger] Add a scheduler component #47112 - 29/07/2020 - @upyx (Sergey Rabochiy) First released on March 2023 | 645,239 downloads (4,947 per day) No longer experimental as of Symfony 6.4
application, like running a task each night at 3 AM, every two weeks except for holidays or any other custom schedule you might need. This component is useful to: Database cleanup Cache clearing Data synchronization Emails Alerts From Symfony Scheduler documentation
from transport "scheduler_default". // The worker will automatically exit once it has received a stop signal via // the messenger:stop-workers command. // Quit the worker with CONTROL-C. // Re-run the command with a -vv option to see logs about consumed messages.
class PlayMusicMessage { public function __construct( public string $clockMusic ) { } } // src/MessageHandler/PlayMusicMessageHandler.php #[ AsMessageHandler ] final class PlayMusicMessageHandler { public function __invoke( PlayMusicMessage $message): void { $command = sprintf('mplayer %s', $message->clockMusic); } } shell_exec($command);
#[ AsSchedule ] final class ClockSchedule implements ScheduleProviderInterface { public function getSchedule(): Schedule { $from = new \DateTimeImmutable ('07:30', new \DateTimeZone ('Europe/Paris')); } } return (new Schedule ()) ->add( RecurringMessage ::every('1 day', new PlayMusicMessage ($clockMusic), $from)) ;
ExcludePublicHolidaysTrigger implements TriggerInterface { public function __construct( private readonly TriggerInterface $inner, // ... ) { } public function __toString(): string { return sprintf('%s (except public holidays)', $this ->inner); } private function isPublicHoliday( \DateTimeImmutable $timestamp): bool { // check if it's a public holiday }
getNextRunDate( \DateTimeImmutable $run): ? \DateTimeImmutable { $nextRun = $this ->inner->getNextRunDate($run); if (null === $nextRun) { return null; } // loop until you get the next run date that is not a public holiday while ( $this ->isPublicHoliday($nextRun)) { $nextRun = $this ->inner->getNextRunDate($nextRun); } } } return $nextRun;
#[ AsSchedule ] final class ClockSchedule implements ScheduleProviderInterface { public function getSchedule(): Schedule { $from = new \DateTimeImmutable ('07:30', new \DateTimeZone ('Europe/Paris')); } } return $this ->schedule ??= (new Schedule ()) ->with( RecurringMessage::trigger( new ExcludePublicHolidaysTrigger ( new PeriodicalTrigger ('1 day', $from), // ... ), new PlayMusicMessage ($clockMusic) ), ) ;
relative format RecurringMessage::every('next friday', new Message()); RecurringMessage::every('first Monday of next month', new Message()); # run at a very specific time every day RecurringMessage::every('1 day', new Message(), from: '14:42'); # you can pass full date/time objects too RecurringMessage::every('1 day', new Message(), from: new \DateTimeImmutable('14:42', new \DateTimeZone('Europe/Paris'))); # define the end of the handling too RecurringMessage::every('1 day', new Message(), until: '2023-09-21'); # you can even use cron expressions RecurringMessage::cron('* * * * *', new Message()); // every minute RecurringMessage::cron('42 14 * * 2', new Message()); // every Tuesday at 14:42 For cron triggers you need to install: dragonmantank/cronexpression