Skip to content

[Scheduler] Changing the scheduler at runtime is almost impossibile? #62727

@gremo

Description

@gremo

Symfony version(s) affected

7.4

Description

I'm referecing this quite old #51553 and mostry the documentation "Strategies for Adding, Removing, and Modifying Entries within the Schedule".

I have to admit that both the change and the documentation presented here leave me a bit perplexed. I'm not an expert in operating system processes or low-level behavior, but something doesn't quite add up for me.

Please correct me if I'm wrong, but typically the scheduler will be launched through a command such as php bin/console messenger:consume scheduler_default or more commonly through a system like Supervisor. In that context, the process does not share memory space with the normal Symfony execution environment (php-fpm, FrankenPHP, etc.). Consequently, the scheduler is a completely separate instance.

Therefore, what is the actual purpose of a method that restarts the scheduler and resets the heap, if it's not possible to call it on the real scheduler instance running inside the worker process?

In my specific case, I'm trying to update the scheduler whenever a task is disabled, removed, or added from my UI. My scheduler is managed by supervisord.

The first “simple” scenario is a single worker process:

[program:messenger]
command=php /app/bin/console messenger:consume --all --time-limit=3600 --no-debug
user=root
numprocs=1
startsecs=0
autostart=true
autorestart=true
startretries=10
process_name=%(program_name)s_%(process_num)02d

In this case, it might be possible to leverage the scheduler by sending an asynchronous message that is handled by the scheduler itself, allowing it to trigger add/remove on the in-memory scheduler instance.

Something like this could work (where AddRecurringMessage and RemoveRecurringMessage are both async):

#[AsSchedule('scheduled_task')]
final class ScheduledTaskProvider implements ScheduleProviderInterface
{
    // ...
    #[AsMessageHandler]
    public function handleAddRecurringMessage(AddRecurringMessage $event): void
    {
        $message = $event->message;
        foreach ($this->schedule->getRecurringMessages() as $m) {
            if ($m->getId() === $message->getId()) {
                return;
            }
        }

        $this->schedule->add($message);
    }

    #[AsMessageHandler]
    public function handleRemoveRecurringMessage(RemoveRecurringMessage $event): void
    {
        $this->schedule->remove($event->message);
    }
}

With multiple workers and processes, things become even more complex.

How to reproduce

Try to add or remove Scheduler messages at runtime.

Possible Solution

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions