8000 [Lock] Split \"StoreInterface\" into multiple interfaces with less re… · symfony/symfony@91fcbea · GitHub
[go: up one dir, main page]

Skip to content

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 91fcbea

Browse files
Simperfitfabpot
authored andcommitted
[Lock] Split \"StoreInterface\" into multiple interfaces with less responsability
1 parent b79a1bf commit 91fcbea

16 files changed

+291
-78
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Lock;
13+
14+
use Symfony\Component\Lock\Exception\LockConflictedException;
15+
use Symfony\Component\Lock\Exception\NotSupportedException;
16+
17+
/**
18+
* @author Hamza Amrouche <hamza.simperfit@gmail.com>
19+
*/
20+
interface BlockingStoreInterface
21+
{
22+
/**
23+
* Waits until a key becomes free, then stores the resource.
24+
*
25+
* If the store does not support this feature it should throw a NotSupportedException.
26+
*
27+
* @throws LockConflictedException
28+
* @throws NotSupportedException
29+
*/
30+
public function waitAndSave(Key $key);
31+
32+
/**
33+
* Checks if the store can wait until a key becomes free before storing the resource.
34+
*/
35+
public function supportsWaitAndSave(): bool;
36+
}

src/Symfony/Component/Lock/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ CHANGELOG
44
4.4.0
55
-----
66

7-
* added InvalidTtlException
8-
7+
* added InvalidTtlException
8+
* deprecated `Symfony\Component\Lock\StoreInterface` in favor of `Symfony\Component\Lock\BlockingStoreInterface` and `Symfony\Component\Lock\PersistStoreInterface`
9+
910
4.2.0
1011
-----
1112

src/Symfony/Component/Lock/Lock.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\Lock\Exception\LockConflictedException;
2020
use Symfony\Component\Lock\Exception\LockExpiredException;
2121
use Symfony\Component\Lock\Exception\LockReleasingException;
22+
use Symfony\Component\Lock\Exception\NotSupportedException;
2223

2324
/**
2425
* Lock is the default implementation of the LockInterface.
@@ -36,12 +37,12 @@ final class Lock implements LockInterface, LoggerAwareInterface
3637
private $dirty = false;
3738

3839
/**
39-
* @param Key $key Resource to lock
40-
* @param StoreInterface $store Store used to handle lock persistence
41-
* @param float|null $ttl Maximum expected lock duration in seconds
42-
* @param bool $autoRelease Whether to automatically release the lock or not when the lock instance is destroyed
40+
* @param Key $key Resource to lock
41+
* @param PersistStoreInterface $store Store used to handle lock persistence
42+
* @param float|null $ttl Maximum expected lock duration in seconds
43+
* @param bool $autoRelease Whether to automatically release the lock or not when the lock instance is destroyed
4344
*/
44-
public function __construct(Key $key, StoreInterface $store, float $ttl = null, bool $autoRelease = true)
45+
public function __construct(Key $key, PersistStoreInterface $store, float $ttl = null, bool $autoRelease = true)
4546
{
4647
$this->store = $store;
4748
$this->key = $key;
@@ -70,6 +71,9 @@ public function acquire($blocking = false)
7071
{
7172
try {
7273
if ($blocking) {
74+
if (!($this->store instanceof StoreInterface) && !($this->store instanceof BlockingStoreInterface && $this->store->supportsWaitAndSave())) {
75+
throw new NotSupportedException(sprintf('The store "%s" does not support blocking locks.', \get_class($this->store)));
76+
}
7377
$this->store->waitAndSave($this->key);
7478
} else {
7579
$this->store->save($this->key);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Lock;
13+
14+
use Symfony\Component\Lock\Exception\LockAcquiringException;
15+
use Symfony\Component\Lock\Exception\LockConflictedException;
16+
use Symfony\Component\Lock\Exception\LockReleasingException;
17+
18+
/**
19+
* @author Jérémy Derussé <jeremy@derusse.com>
20+
*/
21+
interface PersistStoreInterface
22+
{
23+
/**
24+
* Stores the resource if it's not locked by someone else.
25+
*
26+
* @throws LockAcquiringException
27+
* @throws LockConflictedException
28+
*/
29+
public function save(Key $key);
30+
31+
/**
32+
* Removes a resource from the storage.
33+
*
34+
* @throws LockReleasingException
35+
*/
36+
public function delete(Key $key);
37+
38+
/**
39+
* Returns whether or not the resource exists in the storage.
40+
*
41+
* @return bool
42+
*/
43+
public function exists(Key $key);
44+
45+
/**
46+
* Extends the TTL of a resource.
47+
*
48+
* @param float $ttl amount of seconds to keep the lock in the store
49+
*
50+
* @throws LockConflictedException
51+
*/
52+
public function putOffExpiration(Key $key, $ttl);
53+
}

src/Symfony/Component/Lock/Store/CombinedStore.php

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\Lock\Exception\LockConflictedException;
1919
use Symfony\Component\Lock\Exception\NotSupportedException;
2020
use Symfony\Component\Lock\Key;
21+
use Symfony\Component\Lock\PersistStoreInterface;
2122
use Symfony\Component\Lock\StoreInterface;
2223
use Symfony\Component\Lock\Strategy\StrategyInterface;
2324

@@ -26,27 +27,27 @@
2627
*
2728
* @author Jérémy Derussé <jeremy@derusse.com>
2829
*/
29-
class CombinedStore implements StoreInterface, LoggerAwareInterface
30+
class CombinedStore implements StoreInterface, PersistStoreInterface, LoggerAwareInterface
3031
{
3132
use LoggerAwareTrait;
3233
use ExpiringStoreTrait;
3334

34-
/** @var StoreInterface[] */
35+
/** @var PersistStoreInterface[] */
3536
private $stores;
3637
/** @var StrategyInterface */
3738
private $strategy;
3839

3940
/**
40-
* @param StoreInterface[] $stores The list of synchronized stores
41-
* @param StrategyInterface $strategy
41+
* @param PersistStoreInterface[] $stores The list of synchronized stores
42+
* @param StrategyInterface $strategy
4243
*
4344
* @throws InvalidArgumentException
4445
*/
4546
public function __construct(array $stores, StrategyInterface $strategy)
4647
{
4748
foreach ($stores as $store) {
48-
if (!$store instanceof StoreInterface) {
49-
throw new InvalidArgumentException(sprintf('The store must implement "%s". Got "%s".', StoreInterface::class, \get_class($store)));
49+
if (!$store instanceof PersistStoreInterface) {
50+
throw new InvalidArgumentException(sprintf('The store must implement "%s". Got "%s".', PersistStoreInterface::class, \get_class($store)));
5051
}
5152
}
5253

@@ -92,8 +93,12 @@ public function save(Key $key)
9293
throw new LockConflictedException();
9394
}
94< 179B /td>95

96+
/**
97+
* {@inheritdoc}
98+
*/
9599
public function waitAndSave(Key $key)
96100
{
101+
@trigger_error(sprintf('%s::%s has been deprecated since Symfony 4.4 and will be removed in Symfony 5.0.', \get_class($this), __METHOD__), E_USER_DEPRECATED);
97102
throw new NotSupportedException(sprintf('The store "%s" does not supports blocking locks.', \get_class($this)));
98103
}
99104

@@ -181,4 +186,12 @@ public function exists(Key $key)
181186

182187
return false;
183188
}
189+
190+
/**
191+
* {@inheritdoc}
192+
*/
193+
public function supportsWaitAndSave(): bool
194+
{
195+
return false;
196+
}
184197
}

src/Symfony/Component/Lock/Store/FlockStore.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111

1212
namespace Symfony\Component\Lock\Store;
1313

14+
use Symfony\Component\Lock\BlockingStoreInterface;
1415
use Symfony\Component\Lock\Exception\InvalidArgumentException;
1516
use Symfony\Component\Lock\Exception\LockConflictedException;
1617
use Symfony\Component\Lock\Exception\LockStorageException;
1718
use Symfony\Component\Lock\Key;
19+
use Symfony\Component\Lock\PersistStoreInterface;
1820
use Symfony\Component\Lock\StoreInterface;
1921

2022
/**
@@ -27,7 +29,7 @@
2729
* @author Romain Neutron <imprec@gmail.com>
2830
* @author Nicolas Grekas <p@tchwork.com>
2931
*/
30-
class FlockStore implements StoreInterface
32+
class FlockStore implements StoreInterface, BlockingStoreInterface, PersistStoreInterface
3133
{
3234
private $lockPath;
3335

@@ -64,6 +66,14 @@ public function waitAndSave(Key $key)
6466
$this->lock($key, true);
6567
}
6668

69+
/**
70+
* {@inheritdoc}
71+
*/
72+
public function supportsWaitAndSave(): bool
73+
{
74+
return true;
75+
}
76+
6777
private function lock(Key $key, $blocking)
6878
{
6979
// The lock is maybe already acquired.

src/Symfony/Component/Lock/Store/MemcachedStore.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515
use Symfony\Component\Lock\Exception\InvalidTtlException;
1616
use Symfony\Component\Lock\Exception\LockConflictedException;
1717
use Symfony\Component\Lock\Key;
18+
use Symfony\Component\Lock\PersistStoreInterface;
1819
use Symfony\Component\Lock\StoreInterface;
1920

2021
/**
2122
* MemcachedStore is a StoreInterface implementation using Memcached as store engine.
2223
*
2324
* @author Jérémy Derussé <jeremy@derusse.com>
2425
*/
25-
class MemcachedStore implements StoreInterface
26+
class MemcachedStore implements StoreInterface, PersistStoreInterface
2627
{
2728
use ExpiringStoreTrait;
2829

@@ -69,8 +70,12 @@ public function save(Key $key)
6970
$this->checkNotExpired($key);
7071
}
7172

73+
/**
74+
* {@inheritdoc}
75+
*/
7276
public function waitAndSave(Key $key)
7377
{
78+
@trigger_error(sprintf('%s has been deprecated since Symfony 4.4 and will be removed in Symfony 5.0.', __METHOD__));
7479
throw new InvalidArgumentException(sprintf('The store "%s" does not supports blocking locks.', \get_class($this)));
7580
}
7681

src/Symfony/Component/Lock/Store/PdoStore.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\Lock\Exception\LockConflictedException;
2020
use Symfony\Component\Lock\Exception\NotSupportedException;
2121
use Symfony\Component\Lock\Key;
22+
use Symfony\Component\Lock\PersistStoreInterface;
2223
use Symfony\Component\Lock\StoreInterface;
2324

2425
/**
@@ -34,7 +35,7 @@
3435
*
3536
* @author Jérémy Derussé <jeremy@derusse.com>
3637
*/
37-
class PdoStore implements StoreInterface
38+
class PdoStore implements StoreInterface, PersistStoreInterface
3839
{
3940
use ExpiringStoreTrait;
4041

@@ -145,6 +146,7 @@ public function save(Key $key)
145146
*/
146147
public function waitAndSave(Key $key)
147148
{
149+
@trigger_error(sprintf('%s has been deprecated since Symfony 4.4 and will be removed in Symfony 5.0.', __METHOD__));
148150
throw new NotSupportedException(sprintf('The store "%s" does not supports blocking locks.', __METHOD__));
149151
}
150152

src/Symfony/Component/Lock/Store/RedisStore.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@
1717
use Symfony\Component\Lock\Exception\InvalidTtlException;
1818
use Symfony\Component\Lock\Exception\LockConflictedException;
1919
use Symfony\Component\Lock\Key;
20+
use Symfony\Component\Lock\PersistStoreInterface;
2021
use Symfony\Component\Lock\StoreInterface;
2122

2223
/**
2324
* RedisStore is a StoreInterface implementation using Redis as store engine.
2425
*
2526
* @author Jérémy Derussé <jeremy@derusse.com>
2627
*/
27-
class RedisStore implements StoreInterface
28+
class RedisStore implements StoreInterface, PersistStoreInterface
2829
{
2930
use ExpiringStoreTrait;
3031

@@ -77,6 +78,7 @@ public function save(Key $key)
7778
*/
7879
public function waitAndSave(Key $key)
7980
{
81+
@trigger_error(sprintf('%s::%s has been deprecated since Symfony 4.4 and will be removed in Symfony 5.0.', \get_class($this), __METHOD__), E_USER_DEPRECATED);
8082
throw new InvalidArgumentException(sprintf('The store "%s" does not supports blocking locks.', \get_class($this)));
8183
}
8284

src/Symfony/Component/Lock/Store/RetryTillSaveStore.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
use Psr\Log\LoggerAwareInterface;
1515
use Psr\Log\LoggerAwareTrait;
1616
use Psr\Log\NullLogger;
17+
use Symfony\Component\Lock\BlockingStoreInterface;
1718
use Symfony\Component\Lock\Exception\LockConflictedException;
1819
use Symfony\Component\Lock\Key;
20+
use Symfony\Component\Lock\PersistStoreInterface;
1921
use Symfony\Component\Lock\StoreInterface;
2022

2123
/**
@@ -24,7 +26,7 @@
2426
*
2527
* @author Jérémy Derussé <jeremy@derusse.com>
2628
*/
27-
class RetryTillSaveStore implements StoreInterface, LoggerAwareInterface
29+
class RetryTillSaveStore implements PersistStoreInterface, BlockingStoreInterface, StoreInterface, LoggerAwareInterface
2830
{
2931
use LoggerAwareTrait;
3032

@@ -33,11 +35,11 @@ class RetryTillSaveStore implements StoreInterface, LoggerAwareInterface
3335
private $retryCount;
3436

3537
/**
36-
* @param StoreInterface $decorated The decorated StoreInterface
37-
* @param int $retrySleep Duration in ms between 2 retry
38-
* @param int $retryCount Maximum amount of retry
38+
* @param PersistStoreInterface $decorated The decorated StoreInterface
39+
* @param int $retrySleep Duration in ms between 2 retry
40+
* @param int $retryCount Maximum amount of retry
3941
*/
40-
public function __construct(StoreInterface $decorated, int $retrySleep = 100, int $retryCount = PHP_INT_MAX)
42+
public function __construct(PersistStoreInterface $decorated, int $retrySleep = 100, int $retryCount = PHP_INT_MAX)
4143
{
4244
$this->decorated = $decorated;
4345
$this->retrySleep = $retrySleep;
@@ -99,4 +101,12 @@ public function exists(Key $key)
99101
{
100102
return $this->decorated->exists($key);
101103
}
104+
105+
/**
106+
* {@inheritdoc}
107+
*/
108+
public function supportsWaitAndSave(): bool
109+
{
110+
return true;
111+
}
102112
}

0 commit comments

Comments
 (0)
0