-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
StanJansen, tomme87 and rvmourikpriyadi