Skip to content

Commit c43a990

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

20 files changed

+623
-62
lines changed

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
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;
7475
use Symfony\Component\Lock\Store\StoreFactory;
7576
use Symfony\Component\Lock\StoreInterface;
@@ -1564,18 +1565,18 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont
15641565
$storeDsn = $container->resolveEnvPlaceholders($storeDsn, null, $usedEnvs);
15651566
switch (true) {
15661567
case 'flock' === $storeDsn:
1567-
$storeDefinition = new Reference('lock.store.flock');
1568+
$storeDefinition = new Reference('lock.store_persist.flock');
15681569
break;
15691570
case 0 === strpos($storeDsn, 'flock://'):
15701571
$flockPath = substr($storeDsn, 8);
15711572

1572-
$storeDefinitionId = '.lock.flock.store.'.$container->hash($storeDsn);
1573+
$storeDefinitionId = '.lock.flock.store_persist.'.$container->hash($storeDsn);
15731574
$container->register($storeDefinitionId, FlockStore::class)->addArgument($flockPath);
1574-
15751575
$storeDefinition = new Reference($storeDefinitionId);
1576+
15761577
break;
15771578
case 'semaphore' === $storeDsn:
1578-
$storeDefinition = new Reference('lock.store.semaphore');
1579+
$storeDefinition = new Reference('lock.store_persist.semaphore');
15791580
break;
15801581
case $usedEnvs || preg_match('#^[a-z]++://#', $storeDsn):
15811582
if (!$container->hasDefinition($connectionDefinitionId = '.lock_connection.'.$container->hash($storeDsn))) {
@@ -1591,9 +1592,10 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont
15911592
$storeDefinition->setFactory([StoreFactory::class, 'createStore']);
15921593
$storeDefinition->setArguments([new Reference($connectionDefinitionId)]);
15931594

1594-
$container->setDefinition($storeDefinitionId = '.lock.'.$resourceName.'.store.'.$container->hash($storeDsn), $storeDefinition);
1595+
$container->setDefinition($legacyStoreDefinitionId = 'lock.'.$resourceName.'.store.'.$container->hash($storeDsn), $storeDefinition)->setDeprecated(true, 'The "%service_id%" service is deprecated.');
1596+
$container->setDefinition($storeDefinitionId = 'lock.'.$resourceName.'.persist_store.'.$container->hash($storeDsn), $storeDefinition);
15951597

1596-
$storeDefinition = new Reference($storeDefinitionId);
1598+
$storeDefinition = new Reference($legacyStoreDefinitionId);
15971599
break;
15981600
default:
15991601
throw new InvalidArgumentException(sprintf('Lock store DSN "%s" is not valid in resource "%s"', $storeDsn, $resourceName));
@@ -1606,6 +1608,8 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont
16061608
if (\count($storeDefinitions) > 1) {
16071609
$combinedDefinition = new ChildDefinition('lock.store.combined.abstract');
16081610
$combinedDefinition->replaceArgument(0, $storeDefinitions);
1611+
1612+
$container->setDefinition('lock.'.$resourceName.'.persist_store', $combinedDefinition);
16091613
$container->setDefinition('lock.'.$resourceName.'.store', $combinedDefinition);
16101614
} else {
16111615
$container->setAlias('lock.'.$resourceName.'.store', new Alias((string) $storeDefinitions[0], false));
@@ -1628,11 +1632,14 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont
16281632
$container->setAlias('lock.store', new Alias('lock.'.$resourceName.'.store', false));
16291633
$container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false));
16301634
$container->setAlias('lock', new Alias('lock.'.$resourceName, false));
1631-
$container->setAlias(StoreInterface::class, new Alias('lock.store', false));
1635+
$container->setAlias(StoreInterface::class, new Alias('lock.store', false))->setDeprecated(true, 'The "%alias_id%" service is deprecated.');
1636+
$container->setAlias(PersistStoreInterface::class, new Alias('lock.persist_store', false));
1637+
16321638
$container->setAlias(Factory::class, new Alias('lock.factory', false));
16331639
$container->setAlias(LockInterface::class, new Alias('lock', false));
16341640
} else {
1635-
$container->registerAliasForArgument('lock.'.$resourceName.'.store', StoreInterface::class, $resourceName.'.lock.store');
1641+
$container->setAlias(PersistStoreInterface::class, new Alias('lock.persist_store', false));
1642+
$container->registerAliasForArgument('lock.'.$resourceName.'.store', StoreInterface::class, $resourceName.'.lock.store')->setDeprecated(true, 'The "%alias_id%" service is deprecated.');
16361643
$container->registerAliasForArgument('lock.'.$resourceName.'.factory', Factory::class, $resourceName.'.lock.factory');
16371644
$container->registerAliasForArgument('lock.'.$resourceName, LockInterface::class, $resourceName.'.lock');
16381645
}

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+
}

src/Symfony/Component/Lock/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
4.4.0
5+
-----
6+
7+
* deprecated `Symfony\Component\Lock\StoreInterface` in favor of `Symfony\Component\Lock\BlockingStoreInterface`, `Symfony\Component\Lock\ExpiringStoreInterface`
8+
and `Symfony\Component\Lock\ExpiringStoreInterface`
9+
410
4.2.0
511
-----
612

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/Lock.php

Lines changed: 12 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 BlockingStoreInterface && $this->store->supportsWaitAndSave())) {
75+
throw new NotSupportedException();
76+
}
7377
$this->store->waitAndSave($this->key);
7478
} else {
7579
$this->store->save($this->key);
@@ -121,6 +125,9 @@ public function refresh($ttl = null)
121125

122126
try {
123127
$this->key->resetLifetime();
128+
if (!($this->store instanceof ExpiringStoreInterface && $this->store->supportsPutOffExpiration())) {
129+
throw new NotSupportedException();
130+
}
124131
$this->store->putOffExpiration($this->key, $ttl);
125132
$this->dirty = true;
126133

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)
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