-
-
Notifications
You must be signed in to change notification settings - Fork 9
Open
Description
Having ability to run cron tasks using symfony scheduler would be really useful, I don't know currently how should it be handled: using tick, another sub-process or on task handling.
I will try with rewriting Symfony\Component\Scheduler class to make it non-blocking, so I will remove while loop and sleep and run it using tick inside custom configurator, WithScheduler implementing SwooleBundle\SwooleBundle\Server\Configurator.
It is possible, only custom scheduler must be written, something like:
class Scheduler
{
/**
* @var array<MessageGenerator>
*/
private array $generators = [];
private int $index = 0;
/**
* @param iterable<ScheduleProviderInterface> $scheduleProviders
*/
public function __construct(private MessageBusInterface $bus, array $scheduleProviders, private readonly ClockInterface $clock = new Clock(), private readonly ?EventDispatcherInterface $dispatcher = null)
{
foreach ($scheduleProviders as $scheduleProvider) {
$this->addSchedule($scheduleProvider->getSchedule());
}
}
public function addSchedule(Schedule $schedule): void
{
$this->addMessageGenerator(new MessageGenerator($schedule, 'schedule_' . $this->index++, $this->clock));
}
public function addMessageGenerator(MessageGenerator $generator): void
{
$this->generators[] = $generator;
}
public function run(): void
{
foreach ($this->generators as $generator) {
foreach ($generator->getMessages() as $context => $message) {
if (!$this->dispatcher) {
$this->bus->dispatch($message);
continue;
}
$preRunEvent = new PreRunEvent($generator->getSchedule(), $context, $message);
$this->dispatcher->dispatch($preRunEvent);
if ($preRunEvent->shouldCancel()) {
continue;
}
try {
$this->bus->dispatch($message);
$this->dispatcher->dispatch(new PostRunEvent($generator->getSchedule(), $context, $message));
} catch (Throwable $error) {
$failureEvent = new FailureEvent($generator->getSchedule(), $context, $message, $error);
$this->dispatcher->dispatch($failureEvent);
if (!$failureEvent->shouldIgnore()) {
throw $error;
}
}
}
}
}
}
then configured with
\Swoole\Timer::tick(1000, function () {
$this->scheduler->run();
});
and as a result, you are able to provide schedules with any frequency:
return (new Schedule())
->stateful($this->cache)
->with(
RecurringMessage::every(
3,
new DummyCommand()
)
)
;
tacman, peterpeppered and Citizen4our
Metadata
Metadata
Assignees
Labels
No labels
