Open
Description
Symfony version(s) affected
7.1
Description
I'm experiencing an issue with the Scheduler component when setting the --limit
option to 1
.
I have two tasks defined with the #[AsCronTask('* * * * *')]
attribute, so they should run every minute.
Here's what happens :
- The first task is executed.
- The scheduler saves its checkpoint and stops, as expected due to the limit.
- Upon restarting the scheduler, it recalculates its task heap starting from the previously saved checkpoint.
- Both the first and second tasks are rescheduled for the next minute.
- However, the second task is never executed in subsequent runs.
It appears that the scheduler saves the checkpoint even if not all scheduled tasks have been executed. As a result, the second task is perpetually rescheduled but never runs.
Thank you for your assistance.
How to reproduce
- Define two tasks with the
#[AsCronTask('* * * * *')]
attribute. - Start the scheduler with the
--limit=1
option:bin/console scheduler:start --limit=1
. - Observe that only the first task is executed.
- Restart the scheduler.
- Notice that the second task is never executed, even though it's rescheduled.
There is a script simulating this behavior
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Scheduler\Generator\MessageGenerator;
use Symfony\Component\Scheduler\RecurringMessage;
use Symfony\Component\Scheduler\Schedule;
use Symfony\Component\Scheduler\ScheduleProviderInterface;
use Symfony\Contracts\Cache\CacheInterface;
class FirstMessage
{
}
class SecondMessage
{
}
class MyProvider implements ScheduleProviderInterface
{
private CacheInterface $cache;
public function getSchedule(): Schedule
{
return (new Schedule())
->stateful($this->cache ??= new ArrayAdapter())
->add(RecurringMessage::every('5 second', new FirstMessage()))
->add(RecurringMessage::every('5 second', new SecondMessage()));
}
}
function run(): void
{
static $nth = 0;
echo 'Run #'.++$nth."\n";
$generator = new MessageGenerator(new MyProvider(), 'default');
while (true) {
// waiting for messages
foreach ($generator->getMessages() as $context => $message) {
echo 'Message to execute : '.$message::class."\n";
return; // Simulate --limit=1
}
}
}
run(); // The FirstMessage is executed: ok
run(); // The FirstMessage is again executed 5 seconds after, but the SecondMessage is not executed
run(); // again, the FirstMessage is executed, but the SecondMessage is not executed
Results:
Run #1
Message to execute : FirstMessage
Run #2
Message to execute : FirstMessage
Run #3
Message to execute : FirstMessage
Possible Solution
The checkpoint is saved globally to save the last execution of the scheduler.
Maybe we should consider different checkpoints for each message?
Additional Context
No response