bug #38553 [Lock] Reset Key lifetime time before we acquire it (Nyholm)

This PR was merged into the 4.4 branch.

Discussion
----------

[Lock] Reset Key lifetime time before we acquire it

| Q             | A
| ------------- | ---
| Branch?       | 5.1 (maybe lower, I'll check)
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #38541
| License       | MIT
| Doc PR        | n/a

Im out on somewhat deep water now. I am pretty sure we should reset the Key lifetime every time we acquire it. Without it it will me tricky to re-use a lock. (As pointed out by #38541)

@jderusse can you confirm.

Commits
-------

55ad70225a [Lock] Reset Key lifetime time before we acquire it
This commit is contained in:
Fabien Potencier 2020-10-14 11:40:34 +02:00
commit 674382b7ea
2 changed files with 48 additions and 0 deletions

View File

@ -67,6 +67,7 @@ final class Lock implements LockInterface, LoggerAwareInterface
*/
public function acquire($blocking = false): bool
{
$this->key->resetLifetime();
try {
if ($blocking) {
if (!$this->store instanceof StoreInterface && !$this->store instanceof BlockingStoreInterface) {

View File

@ -18,6 +18,7 @@ use Symfony\Component\Lock\Exception\LockConflictedException;
use Symfony\Component\Lock\Key;
use Symfony\Component\Lock\Lock;
use Symfony\Component\Lock\PersistingStoreInterface;
use Symfony\Component\Lock\Store\ExpiringStoreTrait;
use Symfony\Component\Lock\StoreInterface;
/**
@ -392,4 +393,50 @@ class LockTest extends TestCase
yield [[0.1], false];
yield [[-0.1, null], false];
}
/**
* @group time-sensitive
*/
public function testAcquireTwiceWithExpiration()
{
$key = new Key(uniqid(__METHOD__, true));
$store = new class() implements PersistingStoreInterface {
use ExpiringStoreTrait;
private $keys = [];
private $initialTtl = 30;
public function save(Key $key)
{
$key->reduceLifetime($this->initialTtl);
$this->keys[spl_object_hash($key)] = $key;
$this->checkNotExpired($key);
return true;
}
public function delete(Key $key)
{
unset($this->keys[spl_object_hash($key)]);
}
public function exists(Key $key)
{
return isset($this->keys[spl_object_hash($key)]);
}
public function putOffExpiration(Key $key, $ttl)
{
$key->reduceLifetime($ttl);
$this->checkNotExpired($key);
}
};
$ttl = 1;
$lock = new Lock($key, $store, $ttl);
$this->assertTrue($lock->acquire());
$lock->release();
sleep($ttl + 1);
$this->assertTrue($lock->acquire());
$lock->release();
}
}