From 6713d498c7a2b2eda7c236ab5e148a9dd100d52a Mon Sep 17 00:00:00 2001 From: G81BVfaN <131437174+G81BVfaN@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:28:18 +0200 Subject: [PATCH 1/5] - Adding the possibility to specify a TTL (Time To Live) for the lock. --- src/Event.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Event.php b/src/Event.php index 0f67428..999e2e2 100644 --- a/src/Event.php +++ b/src/Event.php @@ -702,10 +702,11 @@ public function user($user) * that will be responsible for the locking. * * @param PersistingStoreInterface|object $store - * + * @param int|null $ttl * @return $this + * @throws \Crunz\Exception\CrunzException */ - public function preventOverlapping(?object $store = null) + public function preventOverlapping(?object $store = null, ?int $ttl = 30) { if (null !== $store && !($store instanceof PersistingStoreInterface)) { $expectedClass = PersistingStoreInterface::class; @@ -721,8 +722,8 @@ public function preventOverlapping(?object $store = null) $this->lockFactory = new LockFactory($lockStore); // Skip the event if it's locked (processing) - $this->skip(function () { - $lock = $this->createLockObject(); + $this->skip(function () use ($ttl) { + $lock = $this->createLockObject($ttl); $lock->acquire(); return !$lock->isAcquired(); @@ -1094,15 +1095,14 @@ public function everySixHours(): self /** * Get the symfony lock object for the task. * + * @param int|null $ttl * @return Lock */ - protected function createLockObject() + protected function createLockObject(?int $ttl = 30) { $this->checkLockFactory(); if (null === $this->lock && null !== $this->lockFactory) { - $ttl = 30; - $this->lock = $this->lockFactory ->createLock($this->lockKey(), $ttl); } From 23ae3a94f7d8a70aecc4afd91c9312e274838c60 Mon Sep 17 00:00:00 2001 From: G81BVfaN <131437174+G81BVfaN@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:30:44 +0200 Subject: [PATCH 2/5] - Adding the possibility to specify a TTL (Time To Live) for the lock. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 6b13059..4fe0eef 100644 --- a/README.md +++ b/README.md @@ -518,6 +518,11 @@ $task ->preventOverlapping($store); ``` +Optionally, you can specify a TTL (Time To Live) for the lock + +```php +$task->preventOverlapping($store, 60); // Lock expires after 60 seconds +``` ## Keeping the Output From 35f387c5d92f7046b6bdc2f5a234befe150a48bb Mon Sep 17 00:00:00 2001 From: akhateeb Date: Thu, 17 Oct 2024 11:32:34 +0200 Subject: [PATCH 3/5] - A little fix suggested from PHP CS Fixer --- src/Event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Event.php b/src/Event.php index 999e2e2..65704c8 100644 --- a/src/Event.php +++ b/src/Event.php @@ -704,7 +704,7 @@ public function user($user) * @param PersistingStoreInterface|object $store * @param int|null $ttl * @return $this - * @throws \Crunz\Exception\CrunzException + * @throws CrunzException */ public function preventOverlapping(?object $store = null, ?int $ttl = 30) { From 0ea5ad9bca90cab4d62e8ceac7af82b28bcce68c Mon Sep 17 00:00:00 2001 From: akhateeb Date: Thu, 21 Nov 2024 12:21:09 +0100 Subject: [PATCH 4/5] - Stop refreshing the lock's TTL, if the lock store supports expiring. --- src/Event.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Event.php b/src/Event.php index 65704c8..fe52c28 100644 --- a/src/Event.php +++ b/src/Event.php @@ -1009,7 +1009,8 @@ public function errorCallbacks() } /** - * If this event is prevented from overlapping, this method should be called regularly to refresh the lock. + * If this event is prevented from overlapping, this method should be called regularly to refresh the lock, + * UNLESS the lock store supports expiring (TTL), which means no refresh is needed. */ public function refreshLock(): void { @@ -1017,6 +1018,13 @@ public function refreshLock(): void return; } + // If the lock has remaining lifetime (i.e. the method returns a float and not NULL), that means the LockStore does support TTL [ 'MemcachedStore', 'MongoDbStore' , 'PdoStore', 'DoctrineDbalStore', 'RedisStore' ] + // @see https://symfony.com/doc/6.4/components/lock.html#available-stores + $remainingLifetime = $this->lock->getRemainingLifetime(); + if (null !== $remainingLifetime) { + return; + }; + $lock = $this->createLockObject(); $remainingLifetime = $lock->getRemainingLifetime(); From 4004aba9881884249a53fd300f54026ea3062940 Mon Sep 17 00:00:00 2001 From: akhateeb Date: Thu, 21 Nov 2024 13:57:19 +0100 Subject: [PATCH 5/5] - Some PHP CS Fixer's fixes & workarounds. --- src/Event.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Event.php b/src/Event.php index fe52c28..8e7a052 100644 --- a/src/Event.php +++ b/src/Event.php @@ -701,9 +701,11 @@ public function user($user) * By default, the lock is acquired through file system locks. Alternatively, you can pass a symfony lock store * that will be responsible for the locking. * - * @param PersistingStoreInterface|object $store - * @param int|null $ttl + * @param PersistingStoreInterface|object|null $store A symfony lock store + * @param int|null $ttl Time To Live of the lock in seconds + * * @return $this + * * @throws CrunzException */ public function preventOverlapping(?object $store = null, ?int $ttl = 30) @@ -1019,11 +1021,11 @@ public function refreshLock(): void } // If the lock has remaining lifetime (i.e. the method returns a float and not NULL), that means the LockStore does support TTL [ 'MemcachedStore', 'MongoDbStore' , 'PdoStore', 'DoctrineDbalStore', 'RedisStore' ] - // @see https://symfony.com/doc/6.4/components/lock.html#available-stores + // @see https://symfony.com/doc/6.4/components/lock.html#available-stores for detailed information $remainingLifetime = $this->lock->getRemainingLifetime(); if (null !== $remainingLifetime) { return; - }; + } $lock = $this->createLockObject(); $remainingLifetime = $lock->getRemainingLifetime(); @@ -1103,7 +1105,8 @@ public function everySixHours(): self /** * Get the symfony lock object for the task. * - * @param int|null $ttl + * @param int|null $ttl Time To Live of the lock in seconds + * * @return Lock */ protected function createLockObject(?int $ttl = 30)