Open
Description
Symfony version(s) affected
6.4..14
Description
When using the Symfony Scheduler component in a stateful configuration with a Doctrine DBAL lock, an exception is thrown due to an invalid TTL computation in Symfony\Component\Scheduler\Generator\Checkpoint::release.
Symfony\Component\Lock\Exception\InvalidTtlException
"Symfony\Component\Lock\Store\DoctrineDbalStore::putOffExpiration()" expects a TTL greater or equals to 1 second. Got "-190.06952309608".
The issue originates in the following line of code:
} elseif ($remaining = $this->lock->getRemainingLifetime()) {
$this->lock->refresh((float) $nextTime->format('U.u') - (float) $now->format('U.u') + $remaining);
}
It appears that in some cases, the computed TTL for the lock becomes negative, causing the InvalidTtlException to be thrown.
I am using mariadb:10.6.19
How to reproduce
#[AsSchedule('my')]
final readonly class MyScheduleProvider implements ScheduleProviderInterface
{
public function __construct(
private CacheInterface $cache,
private LockFactory $lockFactory,
) {
}
public function getSchedule(): Schedule
{
return (new Schedule())
->stateful($this->cache)
->with(RecurringMessage::every(
frequency: '2 minutes',
message: new SometimesHeavyProcess(),
from: new DatePoint('2023-11-10T13:17:55+01:00'),
))
->lock($this->lockFactory->createLock('my_scheduler'))
;
}
}
SometimesHeavyProcess handling sometimes needs more than 2 minutes to finish (it is quite random, depending on app usage).
Steps to Reproduce:
- Configure the scheduler as shown above.
- Trigger the scheduler to run (
bin/console messenger:consume my_scheduler
). - Observe the exceptions thrown due to a negative TTL.
Symfony\Component\Lock\Exception\LockAcquiringException
Failed to define an expiration for the "my_scheduler" lock.
Symfony\Component\Lock\Exception\InvalidTtlException
"Symfony\Component\Lock\Store\DoctrineDbalStore::putOffExpiration()" expects a TTL greater or equals to 1 second. Got "-190.06952309608".
Possible Solution
No response
Additional Context
No response