8000 [Lock] Split "StoreInterface" into multiple interfaces with less resp… · symfony/symfony@5f1ad1f · GitHub
[go: up one dir, main page]

Skip to content

Commit 5f1ad1f

Browse files
committed
[Lock] Split "StoreInterface" into multiple interfaces with less responsability
1 parent 80e28a0 commit 5f1ad1f

21 files changed

+648
-69
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@
7070
use Symfony\Component\Lock\Factory;
7171
use Symfony\Component\Lock\Lock;
7272
use Symfony\Component\Lock\LockInterface;
73+
use Symfony\Component\Lock\PersistStoreInterface;
7374
use Symfony\Component\Lock\Store\FlockStore;
75+
use Symfony\Component\Lock\Store\LegacyStore;
7476
use Symfony\Component\Lock\Store\StoreFactory;
7577
use Symfony\Component\Lock\StoreInterface;
7678
use Symfony\Component\Mailer\Mailer;
@@ -1564,18 +1566,23 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont
15641566
$storeDsn = $container->resolveEnvPlaceholders($storeDsn, null, $usedEnvs);
15651567
switch (true) {
15661568
case 'flock' === $storeDsn:
1567-
$storeDefinition = new Reference('lock.store.flock');
1569+
$storeDefinition = new Definition(LegacyStore::class);
1570+
$storeDefinition->setPublic(false);
1571+
$storeDefinition->setArguments([new Reference('lock.store_persist.flock')]);
15681572
break;
15691573
case 0 === strpos($storeDsn, 'flock://'):
15701574
$flockPath = substr($storeDsn, 8);
15711575

1572-
$storeDefinitionId = '.lock.flock.store.'.$container->hash($storeDsn);
1576+
$storeDefinitionId = '.lock.flock.store_persist.'.$container->hash($storeDsn);
15731577
$container->register($storeDefinitionId, FlockStore::class)->addArgument($flockPath);
1574-
1575-
$storeDefinition = new Reference($storeDefinitionId);
1578+
$storeDefinition = new Definition(LegacyStore::class);
1579+
$storeDefinition->setPublic(false);
1580+
$storeDefinition->setArguments([new Reference($storeDefinitionId)]);
15761581
break;
15771582
case 'semaphore' === $storeDsn:
1578-
$storeDefinition = new Reference('lock.store.semaphore');
1583+
$storeDefinition = new Definition(LegacyStore::class);
1584+
$storeDefinition->setPublic(false);
1585+
$storeDefinition->setArguments([new Reference('lock.store_persist.semaphore')]);
15791586
break;
15801587
case $usedEnvs || preg_match('#^[a-z]++://#', $storeDsn):
15811588
if (!$container->hasDefinition($connectionDefinitionId = '.lock_connection.'.$container->hash($storeDsn))) {
@@ -1586,14 +1593,19 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont
15861593
$container->setDefinition($connectionDefinitionId, $connectionDefinition);
15871594
}
15881595

1589-
$storeDefinition = new Definition(StoreInterface::class);
1596+
$storeDefinition = new Definition(PersistStoreInterface::class);
15901597
$storeDefinition->setPublic(false);
15911598
$storeDefinition->setFactory([StoreFactory::class, 'createStore']);
15921599
$storeDefinition->setArguments([new Reference($connectionDefinitionId)]);
15931600

1594-
$container->setDefinition($storeDefinitionId = '.lock.'.$resourceName.'.store.'.$container->hash($storeDsn), $storeDefinition);
1601+
$legacyStoreDefinition = new Definition(LegacyStore::class);
1602+
$legacyStoreDefinition->setPublic(false);
1603+
$legacyStoreDefinition->setArguments([new Reference($storeDefinition)]);
15951604

1596-
$storeDefinition = new Reference($storeDefinitionId);
1605+
$container->setDefinition($legacyStoreDefinitionId = 'lock.'.$resourceName.'.store.'.$container->hash($storeDsn), $legacyStoreDefinition)->setDeprecated(true, 'The "%service_id%" service is deprecated.');
1606+
$container->setDefinition($storeDefinitionId = 'lock.'.$resourceName.'.persist_store.'.$container->hash($storeDsn), $storeDefinition);
1607+
1608+
$storeDefinition = new Reference($legacyStoreDefinitionId);
15971609
break;
15981610
default:
15991611
throw new InvalidArgumentException(sprintf('Lock store DSN "%s" is not valid in resource "%s"', $storeDsn, $resourceName));
@@ -1606,7 +1618,12 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont
16061618
if (\count($storeDefinitions) > 1) {
16071619
$combinedDefinition = new ChildDefinition('lock.store.combined.abstract');
16081620
$combinedDefinition->replaceArgument(0, $storeDefinitions);
1609-
$container->setDefinition('lock.'.$resourceName.'.store', $combinedDefinition);
1621+
1622+
$legacyDefinition = new ChildDefinition('lock.store.legacy.abstract');
1623+
$legacyDefinition->replaceArgument(0, $combinedDefinition);
1624+
1625+
$container->setDefinition('lock.'.$resourceName.'.persist_store', $combinedDefinition);
1626+
$container->setDefinition('lock.'.$resourceName.'.store', $legacyDefinition);
16101627
} else {
16111628
$container->setAlias('lock.'.$resourceName.'.store', new Alias((string) $storeDefinitions[0], false));
16121629
}
@@ -1628,11 +1645,14 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont
16281645
$container->setAlias('lock.store', new Alias('lock.'.$resourceName.'.store', false));
16291646
$container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false));
16301647
$container->setAlias('lock', new Alias('lock.'.$resourceName, false));
1631-
$container->setAlias(StoreInterface::class, new Alias('lock.store', false));
1648+
$container->setAlias(StoreInterface::class, new Alias('lock.store', false))->setDeprecated(true, 'The "%alias_id%" service is deprecated.');
1649+
$container->setAlias(PersistStoreInterface::class, new Alias('lock.persist_store', false));
1650+
16321651
$container->setAlias(Factory::class, new Alias('lock.factory', false));
16331652
$container->setAlias(LockInterface::class, new Alias('lock', false));
16341653
} else {
1635-
$container->registerAliasForArgument('lock.'.$resourceName.'.store', StoreInterface::class, $resourceName.'.lock.store');
1654+
$container->setAlias(PersistStoreInterface::class, new Alias('lock.persist_store', false));
1655+
$container->registerAliasForArgument('lock.'.$resourceName.'.store', StoreInterface::class, $resourceName.'.lock.store')->setDeprecated(true, 'The "%alias_id%" service is deprecated.');
16361656
$container->registerAliasForArgument('lock.'.$resourceName.'.factory', Factory::class, $resourceName.'.lock.factory');
16371657
$container->registerAliasForArgument('lock.'.$resourceName, LockInterface::class, $resourceName.'.lock');
16381658
}

src/Symfony/Bundle/FrameworkBundle/Resources/config/lock.xml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,49 @@
77
<services>
88
<defaults public="false" />
99

10-
<service id="lock.store.flock" class="Symfony\Component\Lock\Store\FlockStore" />
10+
<service id="lock.store.flock" class="Symfony\Component\Lock\Store\FlockStore" >
11+
<deprecated>The "%service_id%" service is deprecated since Symfony 4.4 use "lock.store_persist.flock" instead.</deprecated>
12+
</service>
13+
<service id="lock.store_persist.flock" class="Symfony\Component\Lock\Store\FlockStore" />
1114

12-
<service id="lock.store.semaphore" class="Symfony\Component\Lock\Store\SemaphoreStore" />
15+
<service id="lock.store.semaphore" class="Symfony\Component\Lock\Store\SemaphoreStore" >
16+
<deprecated>The "%service_id%" service is deprecated since Symfony 4.4 use "lock.store_persist.semaphore" instead.</deprecated>
17+
</service>
18+
<service id="lock.store_persist.semaphore" class="Symfony\Component\Lock\Store\SemaphoreStore" />
19+
<service id="lock.store_persist.memcached.abstract" class="Symfony\Component\Lock\Store\MemcachedStore" abstract="true">
20+
<argument /> <!-- Memcached connection service -->
21+
</service>
22+
23+
<service id="lock.store_persist.redis.abstract" class="Symfony\Component\Lock\Store\RedisStore" abstract="true">
24+
<argument /> <!-- Redis connection service -->
25+
</service>
26+
<service id="lock.store_persist.combined.abstract" class="Symfony\Component\Lock\Store\CombinedStore" abstract="true">
27+
<argument /> <!-- List of stores -->
28+
<argument type="service" id="lock.strategy.majority" /> <!-- Strategy -->
29+
</service>
1330

1431
<service id="lock.store.memcached.abstract" class="Symfony\Component\Lock\Store\MemcachedStore" abstract="true">
32+
<deprecated>The "%service_id%" service is deprecated since Symfony 4.4 use "lock.store_persist.memcached.abstract" instead.</deprecated>
1533
<argument /> <!-- Memcached connection service -->
1634
</service>
1735

1836
<service id="lock.store.redis.abstract" class="Symfony\Component\Lock\Store\RedisStore" abstract="true">
37+
<deprecated>The "%service_id%" service is deprecated since Symfony 4.4 use "lock.store_persist.redis.abstract" instead.</deprecated>
1938
<argument /> <!-- Redis connection service -->
2039
</service>
2140

2241
<service id="lock.store.combined.abstract" class="Symfony\Component\Lock\Store\CombinedStore" abstract="true">
42+
<deprecated>The "%service_id%" service is deprecated since Symfony 4.4 use "lock.store_persist.combined.abstract" instead.</deprecated>
2343
<argument /> <!-- List of stores -->
2444
<argument type="service" id="lock.strategy.majority" /> <!-- Strategy -->
2545
</service>
2646

47+
<service id="lock.store.legacy.abstract" class="Symfony\Component\Lock\Store\LegacyStore" abstract="true">
48+
<argument /> <!-- List of stores -->
49+
<argument type="service" id="lock.strategy.majority" /> <!-- Strategy -->
50+
</service>
51+
52+
2753
<service id="lock.strategy.majority" class="Symfony\Component\Lock\Strategy\ConsensusStrategy" />
2854

2955
<service id="lock.factory.abstract" class="Symfony\Component\Lock\Factory" abstract="true">
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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+
* BlockingStoreInterface defines an interface to manipulate a lock store.
19+
*
20+
* @author Hamza Amrouche <hamza.simperfit@gmail.com>
21+
*/
22+
interface BlockingStoreInterface
23+
{
24+
/**
25+
* Waits until a key becomes free, then stores the resource.
26+
*
27+
* If the store does not support this feature it should throw a NotSupportedException.
28+
*
29+
* @throws LockConflictedException
30+
* @throws NotSupportedException
31+
*/
32+
public function waitAndSave(Key $key);
33+
34+
/**
35+
* Check if the store can wait until a key becomes free before storing the resource.
36+
*/
37+
public function supportsWaitAndSave(): bool;
38+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+
* ExpiringStoreInterface defines an interface to manipulate a lock store.
19+
*
20+
* @author Hamza Amrouche <hamza.simperfit@gmail.com>
21+
*/
22+
interface ExpiringStoreInterface
23+
{
24+
/**
25+
* Extends the ttl of a resource.
26+
*
27+
* If the store does not support this feature it should throw a NotSupportedException.
28+
*
29+
* @param float $ttl amount of seconds to keep the lock in the store
30+
*
31+
* @throws LockConflictedException
32+
* @throws NotSupportedException
33+
*/
34+
public function putOffExpiration(Key $key, $ttl);
35+
36+
/**
37+
* Check if the store supports extending the ttl of a resource.
38+
*
39+
* @throws LockConflictedException
40+
* @throws NotSupportedException
41+
*/
42+
public function supportsPutOffExpiration(): bool;
43+
}

src/Symfony/Component/Lock/Factory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Factory implements LoggerAwareInterface
2626

2727
private $store;
2828

29-
public function __construct(StoreInterface $store)
29+
public function __construct($store)
3030
{
3131
$this->store = $store;
3232

src/Symfony/Component/Lock/Lock.php

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,21 @@ final class Lock implements LockInterface, LoggerAwareInterface
3636
private $dirty = false;
3737

3838
/**
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
39+
* @param Key $key Resource to lock
40+
* @param PersistStoreInterface $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
4343
*/
44-
public function __construct(Key $key, StoreInterface $store, float $ttl = null, bool $autoRelease = true)
44+
public function __construct(Key $key, $store, float $ttl = null, bool $autoRelease = true)
4545
{
46+
if ($store instanceof StoreInterface) {
47+
@trigger_error(sprintf('"%s" is deprecated since Symfony 4.4 and has been splitted into "%s", "%s", "%s".', StoreInterface::class, PersistStoreInterface::class, ExpiringStoreInterface::class, BlockingStoreInterface::class), E_USER_DEPRECATED);
48+
}
49+
50+
if (!($store instanceof PersistStoreInterface || $store instanceof StoreInterface)) {
51+
throw new InvalidArgumentException(sprintf('$store should implement %s.', PersistStoreInterface::class));
52+
}
53+
4654
$this->store = $store;
4755
$this->key = $key;
4856
$this->ttl = $ttl;
@@ -69,7 +77,7 @@ public function __destruct()
6977
public function acquire($blocking = false)
7078
{
7179
try {
72-
if ($blocking) {
80+
if ($blocking && $this->store instanceof BlockingStoreInterface && $this->store->supportsWaitAndSave()) {
7381
$this->store->waitAndSave($this->key);
7482
} else {
7583
$this->store->save($this->key);
@@ -121,7 +129,9 @@ public function refresh($ttl = null)
121129

122130
try {
123131
$this->key->resetLifetime();
124-
$this->store->putOffExpiration($this->key, $ttl);
132+
if ($this->store instanceof ExpiringStoreInterface && $this->store->supportsPutOffExpiration()) {
133+
$this->store->putOffExpiration($this->key, $ttl);
134+
}
125135
$this->dirty = true;
126136

127137
if ($this->key->isExpired()) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
* StoreInterface defines an interface to manipulate a lock store.
20+
*
21+
* @author Jérémy Derussé <jeremy@derusse.com>
22+
*/
23+
interface PersistStoreInterface
24+
{
25+
/**
26+
* Stores the resource if it's not locked by someone else.
27+
*
28+
* @throws LockAcquiringException
29+
* @throws LockConflictedException
30+
*/
31+
public function save(Key $key);
32+
33+
/**
34+
* Removes a resource from the storage.
35+
*
36+
* @throws LockReleasingException
37+
*/
38+
public function delete(Key $key);
39+
40+
/**
41+
* Returns whether or not the resource exists in the storage.
42+
*
43+
* @return bool
44+
*/
45+
public function exists(Key $key);
46+
}

0 commit comments

Comments
 (0)
0