From 629b74e504dc16344a53ef6c300e2b555a83a829 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Thu, 12 Dec 2024 18:58:30 +0100 Subject: [PATCH 01/14] Add a semaphore store based on locks --- .../Component/Semaphore/Store/LockStore.php | 73 +++++++++++++++++++ .../Semaphore/Tests/Store/LockStoreTest.php | 31 ++++++++ 2 files changed, 104 insertions(+) create mode 100644 src/Symfony/Component/Semaphore/Store/LockStore.php create mode 100644 src/Symfony/Component/Semaphore/Tests/Store/LockStoreTest.php diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php new file mode 100644 index 0000000000000..24a4d12529caf --- /dev/null +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -0,0 +1,73 @@ +getLock($key, $ttlInSecond); + } + + public function delete(Key $key): void + { + $this->getLock($key, 0)->release(); + $key->setState(__CLASS__, null); + } + + public function exists(Key $key): bool + { + return $key->hasState(__CLASS__); + } + + public function putOffExpiration(Key $key, float $ttlInSecond): void + { + $lock = $this->getLock($key, $ttlInSecond); + + $lock->refresh($ttlInSecond); + } + + private function getLock(Key $key, float $ttlInSecond): LockInterface + { + $lockName = \base64_encode($key->__toString()); + + if (!$key->hasState(__CLASS__)) { + $limit = $key->getLimit(); + + // use a random start point to have a higher chance to catch a free slot directly + $startPoint = \rand(0, $limit - 1); + + $lock = null; + for ($i = 0; $i < $limit; $i++) { + $index = ($startPoint + $i) % $limit; + $lock = $this->lockFactory->createLock($lockName . '_' . $index, $ttlInSecond); + if ($lock->acquire(blocking: false)) { // use lock if we can acquire it else try to catch next lock + break; + } + $lock = null; + } + + if ($lock === null) { + throw new SemaphoreAcquiringException($key, 'There where no free locks found'); + } + + $key->setState(__CLASS__, $lock); + } + + $lock ??= $key->getState(__CLASS__); + \assert($lock instanceof LockInterface); + + return $lock; + } +} diff --git a/src/Symfony/Component/Semaphore/Tests/Store/LockStoreTest.php b/src/Symfony/Component/Semaphore/Tests/Store/LockStoreTest.php new file mode 100644 index 0000000000000..f3ea398c0f4a3 --- /dev/null +++ b/src/Symfony/Component/Semaphore/Tests/Store/LockStoreTest.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Semaphore\Tests\Store; + +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\FlockStore; +use Symfony\Component\Semaphore\Store\LockStore; +use Symfony\Component\Semaphore\PersistingStoreInterface; + +/** + * @author Alexander Schranz + */ +class LockStoreTest extends AbstractStoreTestCase +{ + public function getStore(): PersistingStoreInterface + { + $lock = new FlockStore(); + $factory = new LockFactory($lock); + + return new LockStore($factory); + } +} From 7371d7ce8e7317e81cb01ee1139ddff77fdd2ccc Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Thu, 12 Dec 2024 19:11:13 +0100 Subject: [PATCH 02/14] Add handling of weight to lock based semaphore --- .../Component/Semaphore/Store/LockStore.php | 73 +++++++++++++++---- .../Tests/Store/AbstractStoreTestCase.php | 1 - 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index 24a4d12529caf..6423876986f60 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -5,6 +5,7 @@ use Symfony\Component\Lock\LockFactory; use Symfony\Component\Lock\LockInterface; use Symfony\Component\Semaphore\Exception\SemaphoreAcquiringException; +use Symfony\Component\Semaphore\Exception\SemaphoreExpiredException; use Symfony\Component\Semaphore\Key; use Symfony\Component\Semaphore\PersistingStoreInterface; @@ -17,57 +18,97 @@ public function __construct( public function save(Key $key, float $ttlInSecond): void { - $this->getLock($key, $ttlInSecond); + $this->getLocks($key, $ttlInSecond, create: true); } public function delete(Key $key): void { - $this->getLock($key, 0)->release(); + foreach ($this->getLocks($key, 0, create: false) as $lock) { + $lock->release(); + } $key->setState(__CLASS__, null); } public function exists(Key $key): bool { - return $key->hasState(__CLASS__); + $locks = $this->getLocks($key, 0, create: false); + + if (\count($locks) !== $key->getWeight()) { + foreach ($locks as $lock) { + $lock->release(); + } + + return false; + } + + return true; } public function putOffExpiration(Key $key, float $ttlInSecond): void { - $lock = $this->getLock($key, $ttlInSecond); + $locks = $this->getLocks($key, $ttlInSecond, create: false); + foreach ($locks as $lock) { + if ($lock->isExpired()) { + foreach ($locks as $lock) { + $lock->release(); + } + + throw new SemaphoreExpiredException($key, 'One or multiple locks are already expired.'); + } + + $lock->refresh($ttlInSecond); + } + + if (\count($locks) !== $key->getWeight()) { - $lock->refresh($ttlInSecond); + foreach ($locks as $lock) { + $lock->release(); + } + + throw new SemaphoreExpiredException($key, 'One or multiple locks were not even acquired.'); + } } - private function getLock(Key $key, float $ttlInSecond): LockInterface + /** + * @return iterable + */ + private function getLocks(Key $key, float $ttlInSecond, bool $create): iterable { $lockName = \base64_encode($key->__toString()); - if (!$key->hasState(__CLASS__)) { + $locks = []; + if (!$key->hasState(__CLASS__) && $create) { $limit = $key->getLimit(); // use a random start point to have a higher chance to catch a free slot directly $startPoint = \rand(0, $limit - 1); - $lock = null; for ($i = 0; $i < $limit; $i++) { $index = ($startPoint + $i) % $limit; + $lock = $this->lockFactory->createLock($lockName . '_' . $index, $ttlInSecond); if ($lock->acquire(blocking: false)) { // use lock if we can acquire it else try to catch next lock - break; + $locks[] = $lock; + + if (\count($locks) === $key->getWeight()) { + break; + } } - $lock = null; } - if ($lock === null) { + if (\count($locks) !== $key->getWeight()) { + foreach ($locks as $lock) { + $lock->release(); + } + throw new SemaphoreAcquiringException($key, 'There where no free locks found'); } - $key->setState(__CLASS__, $lock); + $key->setState(__CLASS__, $locks); + } elseif ($key->hasState(__CLASS__)) { + $locks = $key->getState(__CLASS__); } - $lock ??= $key->getState(__CLASS__); - \assert($lock instanceof LockInterface); - - return $lock; + return $locks; } } diff --git a/src/Symfony/Component/Semaphore/Tests/Store/AbstractStoreTestCase.php b/src/Symfony/Component/Semaphore/Tests/Store/AbstractStoreTestCase.php index 4cd89458f5d92..aafd59adf93bd 100644 --- a/src/Symfony/Component/Semaphore/Tests/Store/AbstractStoreTestCase.php +++ b/src/Symfony/Component/Semaphore/Tests/Store/AbstractStoreTestCase.php @@ -204,7 +204,6 @@ public function testPutOffExpirationWhenSaveHasNotBeenCalled() $key1 = new Key(__METHOD__, 4, 2); $this->expectException(SemaphoreExpiredException::class); - $this->expectExceptionMessage('The semaphore "Symfony\Component\Semaphore\Tests\Store\AbstractStoreTestCase::testPutOffExpirationWhenSaveHasNotBeenCalled" has expired: the script returns a positive number.'); $store->putOffExpiration($key1, 20); } From ca585f7d6e459f13c1b121c574f4214a80781d2a Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Thu, 12 Dec 2024 19:27:00 +0100 Subject: [PATCH 03/14] Add license header, update code style --- .../Component/Semaphore/Store/LockStore.php | 18 +++++++++++++----- .../Semaphore/Tests/Store/LockStoreTest.php | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index 6423876986f60..2535b848b18eb 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Semaphore\Store; use Symfony\Component\Lock\LockFactory; @@ -60,7 +69,6 @@ public function putOffExpiration(Key $key, float $ttlInSecond): void } if (\count($locks) !== $key->getWeight()) { - foreach ($locks as $lock) { $lock->release(); } @@ -74,19 +82,19 @@ public function putOffExpiration(Key $key, float $ttlInSecond): void */ private function getLocks(Key $key, float $ttlInSecond, bool $create): iterable { - $lockName = \base64_encode($key->__toString()); + $lockName = base64_encode($key->__toString()); $locks = []; if (!$key->hasState(__CLASS__) && $create) { $limit = $key->getLimit(); // use a random start point to have a higher chance to catch a free slot directly - $startPoint = \rand(0, $limit - 1); + $startPoint = rand(0, $limit - 1); - for ($i = 0; $i < $limit; $i++) { + for ($i = 0; $i < $limit; ++$i) { $index = ($startPoint + $i) % $limit; - $lock = $this->lockFactory->createLock($lockName . '_' . $index, $ttlInSecond); + $lock = $this->lockFactory->createLock($lockName.'_'.$index, $ttlInSecond); if ($lock->acquire(blocking: false)) { // use lock if we can acquire it else try to catch next lock $locks[] = $lock; diff --git a/src/Symfony/Component/Semaphore/Tests/Store/LockStoreTest.php b/src/Symfony/Component/Semaphore/Tests/Store/LockStoreTest.php index f3ea398c0f4a3..f84ecfafd6870 100644 --- a/src/Symfony/Component/Semaphore/Tests/Store/LockStoreTest.php +++ b/src/Symfony/Component/Semaphore/Tests/Store/LockStoreTest.php @@ -13,8 +13,8 @@ use Symfony\Component\Lock\LockFactory; use Symfony\Component\Lock\Store\FlockStore; -use Symfony\Component\Semaphore\Store\LockStore; use Symfony\Component\Semaphore\PersistingStoreInterface; +use Symfony\Component\Semaphore\Store\LockStore; /** * @author Alexander Schranz From 4f7ca2044c986a5da1a5f971c51c30fac3492635 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Thu, 12 Dec 2024 19:31:58 +0100 Subject: [PATCH 04/14] Define optional requirement to symfony/lock --- src/Symfony/Component/Semaphore/Store/LockStore.php | 3 +++ src/Symfony/Component/Semaphore/composer.json | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index 2535b848b18eb..ba0b7c152779f 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -18,6 +18,9 @@ use Symfony\Component\Semaphore\Key; use Symfony\Component\Semaphore\PersistingStoreInterface; +/** + * @author Alexander Schranz + */ class LockStore implements PersistingStoreInterface { public function __construct( diff --git a/src/Symfony/Component/Semaphore/composer.json b/src/Symfony/Component/Semaphore/composer.json index a620c60cca25a..dbda8ea22412a 100644 --- a/src/Symfony/Component/Semaphore/composer.json +++ b/src/Symfony/Component/Semaphore/composer.json @@ -27,7 +27,8 @@ "predis/predis": "^1.1|^2.0" }, "conflict": { - "symfony/cache": "<6.4" + "symfony/cache": "<6.4", + "symfony/lock": "<5.4 || >=8.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Semaphore\\": "" }, From 79c5b8449cd531ddd8e83cf1ae9d52ca0ee4aa6a Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Thu, 12 Dec 2024 19:42:36 +0100 Subject: [PATCH 05/14] Add validation of the returned locks --- src/Symfony/Component/Semaphore/Store/LockStore.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index ba0b7c152779f..42043fecbc805 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -81,9 +81,9 @@ public function putOffExpiration(Key $key, float $ttlInSecond): void } /** - * @return iterable + * @return array */ - private function getLocks(Key $key, float $ttlInSecond, bool $create): iterable + private function getLocks(Key $key, float $ttlInSecond, bool $create): array { $lockName = base64_encode($key->__toString()); @@ -118,6 +118,15 @@ private function getLocks(Key $key, float $ttlInSecond, bool $create): iterable $key->setState(__CLASS__, $locks); } elseif ($key->hasState(__CLASS__)) { $locks = $key->getState(__CLASS__); + \assert((function () use ($locks) { + foreach ($locks as $lock) { + if (!$lock instanceof LockInterface) { + return false; + } + } + + return true; + })() === true, 'Locks must be an array of LockInterface'); } return $locks; From f4a3cb1463742ee9def36cf03f14913863f19126 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Thu, 12 Dec 2024 19:50:25 +0100 Subject: [PATCH 06/14] Require dev symfony/lock component --- src/Symfony/Component/Semaphore/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Semaphore/composer.json b/src/Symfony/Component/Semaphore/composer.json index dbda8ea22412a..8b67730598e81 100644 --- a/src/Symfony/Component/Semaphore/composer.json +++ b/src/Symfony/Component/Semaphore/composer.json @@ -24,7 +24,8 @@ "psr/log": "^1|^2|^3" }, "require-dev": { - "predis/predis": "^1.1|^2.0" + "predis/predis": "^1.1|^2.0", + "symfony/lock": "^5.4 || ^6.0 || ^7.0" }, "conflict": { "symfony/cache": "<6.4", From 2d18f6cb0f9fe2545f1f4fcf93ecf6ec3fe1de00 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Fri, 13 Dec 2024 09:43:12 +0100 Subject: [PATCH 07/14] Add early return if we can not get enough locks --- src/Symfony/Component/Semaphore/Store/LockStore.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index 42043fecbc805..1c6982daaed5f 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -104,10 +104,20 @@ private function getLocks(Key $key, float $ttlInSecond, bool $create): array if (\count($locks) === $key->getWeight()) { break; } + + continue; + } + + $acquired = \count($locks); + $required = $key->getWeight(); + $remaining = $key->getLimit() - $i; + if (($acquired + $remaining) < $required) { // no chance to get enough locks + break; } } if (\count($locks) !== $key->getWeight()) { + // release already acquired locks not get the amount which is required foreach ($locks as $lock) { $lock->release(); } From 84e0607598b3976e8ea64a8b4c63682279d517aa Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Fri, 13 Dec 2024 10:32:53 +0100 Subject: [PATCH 08/14] Remove type check for array LockInterface --- src/Symfony/Component/Semaphore/Store/LockStore.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index 1c6982daaed5f..82d54000a8d56 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -128,15 +128,6 @@ private function getLocks(Key $key, float $ttlInSecond, bool $create): array $key->setState(__CLASS__, $locks); } elseif ($key->hasState(__CLASS__)) { $locks = $key->getState(__CLASS__); - \assert((function () use ($locks) { - foreach ($locks as $lock) { - if (!$lock instanceof LockInterface) { - return false; - } - } - - return true; - })() === true, 'Locks must be an array of LockInterface'); } return $locks; From 50b835e28e0f1af66b33317cfd76313859b9a330 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 8 Jan 2025 13:15:58 +0100 Subject: [PATCH 09/14] Split createLock in getExistingLocks and createLocks methods and releaseLocks correctly on failing semphore acquired --- .../Component/Semaphore/Store/LockStore.php | 118 ++++++++++-------- 1 file changed, 66 insertions(+), 52 deletions(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index 82d54000a8d56..9581807fed720 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -30,40 +30,41 @@ public function __construct( public function save(Key $key, float $ttlInSecond): void { - $this->getLocks($key, $ttlInSecond, create: true); + $locks = $this->getExistingLocks($key); + + if ([] !== $locks) { + return; + } + + $locks = $this->createLocks($key, $ttlInSecond); + + $key->setState(__CLASS__, $locks); } public function delete(Key $key): void { - foreach ($this->getLocks($key, 0, create: false) as $lock) { - $lock->release(); - } - $key->setState(__CLASS__, null); + $this->releaseLocks($this->getExistingLocks($key) , $key); } public function exists(Key $key): bool { - $locks = $this->getLocks($key, 0, create: false); + $locks = $this->getExistingLocks($key); - if (\count($locks) !== $key->getWeight()) { - foreach ($locks as $lock) { - $lock->release(); - } - - return false; + if (\count($locks) === $key->getWeight()) { + return true; } - return true; + $this->releaseLocks($this->getExistingLocks($key) , $key); + + return false; } public function putOffExpiration(Key $key, float $ttlInSecond): void { - $locks = $this->getLocks($key, $ttlInSecond, create: false); + $locks = $this->getExistingLocks($key); foreach ($locks as $lock) { if ($lock->isExpired()) { - foreach ($locks as $lock) { - $lock->release(); - } + $this->releaseLocks($locks, $key); throw new SemaphoreExpiredException($key, 'One or multiple locks are already expired.'); } @@ -72,62 +73,75 @@ public function putOffExpiration(Key $key, float $ttlInSecond): void } if (\count($locks) !== $key->getWeight()) { - foreach ($locks as $lock) { - $lock->release(); - } + $this->releaseLocks($locks, $key); throw new SemaphoreExpiredException($key, 'One or multiple locks were not even acquired.'); } } /** - * @return array + * @param array $locks */ - private function getLocks(Key $key, float $ttlInSecond, bool $create): array + private function releaseLocks(array $locks, Key $key): void { - $lockName = base64_encode($key->__toString()); + foreach ($locks as $lock) { + $lock->release(); + } - $locks = []; - if (!$key->hasState(__CLASS__) && $create) { - $limit = $key->getLimit(); + $key->setState(__CLASS__, null); + } - // use a random start point to have a higher chance to catch a free slot directly - $startPoint = rand(0, $limit - 1); + /** + * @return array + */ + private function getExistingLocks(Key $key): array + { + if ($key->hasState(__CLASS__)) { + return $key->getState(__CLASS__); + } - for ($i = 0; $i < $limit; ++$i) { - $index = ($startPoint + $i) % $limit; + return []; + } + + /** + * @return array + */ + private function createLocks(Key $key, float $ttlInSecond): array + { + $locks = []; + $lockName = base64_encode($key->__toString()); + $limit = $key->getLimit(); - $lock = $this->lockFactory->createLock($lockName.'_'.$index, $ttlInSecond); - if ($lock->acquire(blocking: false)) { // use lock if we can acquire it else try to catch next lock - $locks[] = $lock; + // use a random start point to have a higher chance to catch a free slot directly + $startPoint = rand(0, $limit - 1); - if (\count($locks) === $key->getWeight()) { - break; - } + for ($i = 0; $i < $limit; ++$i) { + $index = ($startPoint + $i) % $limit; - continue; - } + $lock = $this->lockFactory->createLock($lockName.'_'.$index, $ttlInSecond); + if ($lock->acquire(blocking: false)) { // use lock if we can acquire it else try to catch next lock + $locks[] = $lock; - $acquired = \count($locks); - $required = $key->getWeight(); - $remaining = $key->getLimit() - $i; - if (($acquired + $remaining) < $required) { // no chance to get enough locks + if (\count($locks) === $key->getWeight()) { break; } - } - if (\count($locks) !== $key->getWeight()) { - // release already acquired locks not get the amount which is required - foreach ($locks as $lock) { - $lock->release(); - } + continue; + } - throw new SemaphoreAcquiringException($key, 'There where no free locks found'); + $acquired = \count($locks); + $required = $key->getWeight(); + $remaining = $key->getLimit() - $i; + if (($acquired + $remaining) < $required) { // no chance to get enough locks + break; } + } + + if (\count($locks) !== $key->getWeight()) { + // release already acquired locks not get the amount which is required + $this->releaseLocks($locks, $key); - $key->setState(__CLASS__, $locks); - } elseif ($key->hasState(__CLASS__)) { - $locks = $key->getState(__CLASS__); + throw new SemaphoreAcquiringException($key, 'There were no free locks found'); } return $locks; From 387f6b312a23620458af453767d95b8d17303a0d Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 8 Jan 2025 13:16:10 +0100 Subject: [PATCH 10/14] Remove conflict to symfony/lock --- src/Symfony/Component/Semaphore/composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/Semaphore/composer.json b/src/Symfony/Component/Semaphore/composer.json index 8b67730598e81..6c736a6e466c3 100644 --- a/src/Symfony/Component/Semaphore/composer.json +++ b/src/Symfony/Component/Semaphore/composer.json @@ -28,8 +28,7 @@ "symfony/lock": "^5.4 || ^6.0 || ^7.0" }, "conflict": { - "symfony/cache": "<6.4", - "symfony/lock": "<5.4 || >=8.0" + "symfony/cache": "<6.4" }, "autoload": { "psr-4": { "Symfony\\Component\\Semaphore\\": "" }, From 2e1159ca5dde065bde0ce47740da8eb1a5424596 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 8 Jan 2025 13:18:23 +0100 Subject: [PATCH 11/14] Remove duplicated call to getExistingLocks --- src/Symfony/Component/Semaphore/Store/LockStore.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index 9581807fed720..b2f9697db63ef 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -54,7 +54,7 @@ public function exists(Key $key): bool return true; } - $this->releaseLocks($this->getExistingLocks($key) , $key); + $this->releaseLocks($locks , $key); return false; } From 6a3c484f89a41118700e5f0bff18745339521393 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 8 Jan 2025 14:25:43 +0100 Subject: [PATCH 12/14] Make final, remove named arguments, update comment for release already acquired locks --- src/Symfony/Component/Semaphore/Store/LockStore.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index b2f9697db63ef..5c01154a21429 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -21,7 +21,7 @@ /** * @author Alexander Schranz */ -class LockStore implements PersistingStoreInterface +final class LockStore implements PersistingStoreInterface { public function __construct( private readonly LockFactory $lockFactory, @@ -119,7 +119,7 @@ private function createLocks(Key $key, float $ttlInSecond): array $index = ($startPoint + $i) % $limit; $lock = $this->lockFactory->createLock($lockName.'_'.$index, $ttlInSecond); - if ($lock->acquire(blocking: false)) { // use lock if we can acquire it else try to catch next lock + if ($lock->acquire(false)) { // use lock if we can acquire it else try to catch next lock $locks[] = $lock; if (\count($locks) === $key->getWeight()) { @@ -138,7 +138,7 @@ private function createLocks(Key $key, float $ttlInSecond): array } if (\count($locks) !== $key->getWeight()) { - // release already acquired locks not get the amount which is required + // release already acquired locks because not got the amount of locks which were required $this->releaseLocks($locks, $key); throw new SemaphoreAcquiringException($key, 'There were no free locks found'); From 92a1d0b267bd1f4994c15f373c93d5de03b83197 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Thu, 9 Jan 2025 09:50:22 +0100 Subject: [PATCH 13/14] Fix coding standards --- src/Symfony/Component/Semaphore/Store/LockStore.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index 5c01154a21429..726323564f47e 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -43,7 +43,7 @@ public function save(Key $key, float $ttlInSecond): void public function delete(Key $key): void { - $this->releaseLocks($this->getExistingLocks($key) , $key); + $this->releaseLocks($this->getExistingLocks($key), $key); } public function exists(Key $key): bool @@ -54,7 +54,7 @@ public function exists(Key $key): bool return true; } - $this->releaseLocks($locks , $key); + $this->releaseLocks($locks, $key); return false; } From 2f035bcb89657309f331466b8f070a22b7e9ba47 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 30 Apr 2025 09:40:22 +0200 Subject: [PATCH 14/14] Do not auto release locks of semaphore --- src/Symfony/Component/Semaphore/Store/LockStore.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Semaphore/Store/LockStore.php b/src/Symfony/Component/Semaphore/Store/LockStore.php index 726323564f47e..5cc77ff7ca1b2 100644 --- a/src/Symfony/Component/Semaphore/Store/LockStore.php +++ b/src/Symfony/Component/Semaphore/Store/LockStore.php @@ -118,7 +118,7 @@ private function createLocks(Key $key, float $ttlInSecond): array for ($i = 0; $i < $limit; ++$i) { $index = ($startPoint + $i) % $limit; - $lock = $this->lockFactory->createLock($lockName.'_'.$index, $ttlInSecond); + $lock = $this->lockFactory->createLock($lockName.'_'.$index, $ttlInSecond, false); if ($lock->acquire(false)) { // use lock if we can acquire it else try to catch next lock $locks[] = $lock; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy