keep cache namespaces separated by environment of the app. The `%kernel.container_class%` (which includes the environment)
used to be added by default to the seed, which is not the case anymore. This allows sharing caches between
apps or different environments.
- * Deprecated the `lock.RESOURCE_NAME` service and the `lock` and `LockInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead.
+ * Deprecated the `lock.RESOURCE_NAME` and `lock.RESOURCE_NAME.store` services and the `lock`, `LockInterface`, `lock.store` and `PersistingStoreInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead.
Form
----
* Removed `session.attribute_bag` service and `session.flash_bag` service.
* The `form.factory`, `form.type.file`, `translator`, `security.csrf.token_manager`, `serializer`,
`cache_clearer`, `filesystem` and `validator` services are now private.
- * Removed the `lock.RESOURCE_NAME` service and the `lock` and `LockInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead.
+ * Removed the `lock.RESOURCE_NAME` and `lock.RESOURCE_NAME.store` services and the `lock`, `LockInterface`, `lock.store` and `PersistingStoreInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead.
HttpFoundation
--------------
* added `assertCheckboxChecked()` and `assertCheckboxNotChecked()` in `WebTestCase`
* added `assertFormValue()` and `assertNoFormValue()` in `WebTestCase`
* Added "--as-tree=3" option to `translation:update` command to dump messages as a tree-like structure. The given value defines the level where to switch to inline YAML
- * Deprecated the `lock.RESOURCE_NAME` service and the `lock` and `LockInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead.
+ * Deprecated the `lock.RESOURCE_NAME` and `lock.RESOURCE_NAME.store` services and the `lock`, `LockInterface`, `lock.store` and `PersistingStoreInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead.
5.1.0
-----
if (\count($storeDefinitions) > 1) {
$combinedDefinition = new ChildDefinition('lock.store.combined.abstract');
$combinedDefinition->replaceArgument(0, $storeDefinitions);
- $container->setDefinition('lock.'.$resourceName.'.store', $combinedDefinition);
+ $container->setDefinition('lock.'.$resourceName.'.store', $combinedDefinition)->setDeprecated('symfony/framework-bundle', '5.2', 'The "%service_id%" service is deprecated, use "lock.'.$resourceName.'.factory" instead.');
+ $container->setDefinition($storeDefinitionId = '.lock.'.$resourceName.'.store.'.$container->hash($resourceStores), $combinedDefinition);
} else {
- $container->setAlias('lock.'.$resourceName.'.store', new Alias((string) $storeDefinitions[0], false));
+ $container->setAlias('lock.'.$resourceName.'.store', (new Alias($storeDefinitionId, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "lock.'.$resourceName.'.factory" instead.'));
}
// Generate factories for each resource
$factoryDefinition = new ChildDefinition('lock.factory.abstract');
- $factoryDefinition->replaceArgument(0, new Reference('lock.'.$resourceName.'.store'));
+ $factoryDefinition->replaceArgument(0, new Reference($storeDefinitionId));
$container->setDefinition('lock.'.$resourceName.'.factory', $factoryDefinition);
// Generate services for lock instances
// provide alias for default resource
if ('default' === $resourceName) {
- $container->setAlias('lock.store', new Alias('lock.'.$resourceName.'.store', false));
+ $container->setAlias('lock.store', (new Alias($storeDefinitionId, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "lock.factory" instead.'));
$container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false));
$container->setAlias('lock', (new Alias('lock.'.$resourceName, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "lock.factory" instead.'));
- $container->setAlias(PersistingStoreInterface::class, new Alias('lock.store', false));
+ $container->setAlias(PersistingStoreInterface::class, (new Alias($storeDefinitionId, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "'.LockFactory::class.'" instead.'));
$container->setAlias(LockFactory::class, new Alias('lock.factory', false));
$container->setAlias(LockInterface::class, (new Alias('lock.'.$resourceName, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "'.LockFactory::class.'" instead.'));
} else {
- $container->registerAliasForArgument('lock.'.$resourceName.'.store', PersistingStoreInterface::class, $resourceName.'.lock.store');
+ $container->registerAliasForArgument($storeDefinitionId, PersistingStoreInterface::class, $resourceName.'.lock.store')->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "'.LockFactory::class.' '.$resourceName.'LockFactory" instead.');
$container->registerAliasForArgument('lock.'.$resourceName.'.factory', LockFactory::class, $resourceName.'.lock.factory');
$container->registerAliasForArgument('lock.'.$resourceName, LockInterface::class, $resourceName.'.lock')->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "'.LockFactory::class.' $'.$resourceName.'LockFactory" instead.');
}
* deprecated `RetryTillSaveStore`, logic has been moved in `Lock` and is not needed anymore.
* added `InMemoryStore`
* added `PostgreSqlStore`
+ * added the `LockFactory::CreateLockFromKey()` method.
5.1.0
-----
*/
public function createLock(string $resource, ?float $ttl = 300.0, bool $autoRelease = true): LockInterface
{
- $lock = new Lock(new Key($resource), $this->store, $ttl, $autoRelease);
+ return $this->createLockFromKey(new Key($resource), $ttl, $autoRelease);
+ }
+
+ /**
+ * Creates a lock from the given key.
+ *
+ * @param Key $key The key containing the lock's state
+ * @param float|null $ttl Maximum expected lock duration in seconds
+ * @param bool $autoRelease Whether to automatically release the lock or not when the lock instance is destroyed
+ */
+ public function createLockFromKey(Key $key, ?float $ttl = 300.0, bool $autoRelease = true): LockInterface
+ {
+ $lock = new Lock($key, $this->store, $ttl, $autoRelease);
$lock->setLogger($this->logger);
return $lock;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
+use Symfony\Component\Lock\Key;
use Symfony\Component\Lock\LockFactory;
-use Symfony\Component\Lock\LockInterface;
use Symfony\Component\Lock\PersistingStoreInterface;
/**
public function testCreateLock()
{
$store = $this->getMockBuilder(PersistingStoreInterface::class)->getMock();
+ $store->expects($this->any())->method('exists')->willReturn(false);
+
+ $keys = [];
+ $store
+ ->expects($this->exactly(2))
+ ->method('save')
+ ->with($this->callback(function ($key) use (&$keys) {
+ $keys[] = $key;
+
+ return true;
+ }))
+ ->willReturn(true);
+
$logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
$factory = new LockFactory($store);
$factory->setLogger($logger);
- $lock = $factory->createLock('foo');
+ $lock1 = $factory->createLock('foo');
+ $lock2 = $factory->createLock('foo');
+
+ // assert lock1 and lock2 don't share the same state
+ $lock1->acquire();
+ $lock2->acquire();
+
+ $this->assertNotSame($keys[0], $keys[1]);
+ }
+
+ public function testCreateLockFromKey()
+ {
+ $store = $this->getMockBuilder(PersistingStoreInterface::class)->getMock();
+ $store->expects($this->any())->method('exists')->willReturn(false);
+
+ $keys = [];
+ $store
+ ->expects($this->exactly(2))
+ ->method('save')
+ ->with($this->callback(function ($key) use (&$keys) {
+ $keys[] = $key;
+
+ return true;
+ }))
+ ->willReturn(true);
+
+ $logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
+ $factory = new LockFactory($store);
+ $factory->setLogger($logger);
+
+ $key = new Key('foo');
+ $lock1 = $factory->createLockFromKey($key);
+ $lock2 = $factory->createLockFromKey($key);
+
+ // assert lock1 and lock2 share the same state
+ $lock1->acquire();
+ $lock2->acquire();
- $this->assertInstanceOf(LockInterface::class, $lock);
+ $this->assertSame($keys[0], $keys[1]);
}
}
*/
public function createSemaphore(string $resource, int $limit, int $weight = 1, ?float $ttlInSecond = 300.0, bool $autoRelease = true): SemaphoreInterface
{
- $semaphore = new Semaphore(new Key($resource, $limit, $weight), $this->store, $ttlInSecond, $autoRelease);
+ return $this->createSemaphoreFromKey(new Key($resource, $limit, $weight), $ttlInSecond, $autoRelease);
+ }
+
+ /**
+ * @param float|null $ttlInSecond Maximum expected semaphore duration in seconds
+ * @param bool $autoRelease Whether to automatically release the semaphore or not when the semaphore instance is destroyed
+ */
+ public function createSemaphoreFromKey(Key $key, ?float $ttlInSecond = 300.0, bool $autoRelease = true): SemaphoreInterface
+ {
+ $semaphore = new Semaphore($key, $this->store, $ttlInSecond, $autoRelease);
$semaphore->setLogger($this->logger);
return $semaphore;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
+use Symfony\Component\Semaphore\Key;
use Symfony\Component\Semaphore\PersistingStoreInterface;
use Symfony\Component\Semaphore\SemaphoreFactory;
-use Symfony\Component\Semaphore\SemaphoreInterface;
/**
* @author Jérémy Derussé <jeremy@derusse.com>
public function testCreateSemaphore()
{
$store = $this->getMockBuilder(PersistingStoreInterface::class)->getMock();
+
+ $keys = [];
+ $store
+ ->expects($this->exactly(2))
+ ->method('save')
+ ->with($this->callback(function ($key) use (&$keys) {
+ $keys[] = $key;
+
+ return true;
+ }))
+ ->willReturn(true);
+
$logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
$factory = new SemaphoreFactory($store);
$factory->setLogger($logger);
- $semaphore = $factory->createSemaphore('foo', 4);
+ $semaphore1 = $factory->createSemaphore('foo', 4);
+ $semaphore2 = $factory->createSemaphore('foo', 4);
+
+ // assert lock1 and lock2 don't share the same state
+ $semaphore1->acquire();
+ $semaphore2->acquire();
+
+ $this->assertNotSame($keys[0], $keys[1]);
+ }
+
+ public function testCreateSemaphoreFromKey()
+ {
+ $store = $this->getMockBuilder(PersistingStoreInterface::class)->getMock();
+
+ $keys = [];
+ $store
+ ->expects($this->exactly(2))
+ ->method('save')
+ ->with($this->callback(function ($key) use (&$keys) {
+ $keys[] = $key;
+
+ return true;
+ }))
+ ->willReturn(true);
+
+ $logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
+ $factory = new SemaphoreFactory($store);
+ $factory->setLogger($logger);
+
+ $key = new Key('foo', 4);
+ $semaphore1 = $factory->createSemaphoreFromKey($key);
+ $semaphore2 = $factory->createSemaphoreFromKey($key);
+
+ // assert lock1 and lock2 share the same state
+ $semaphore1->acquire();
+ $semaphore2->acquire();
- $this->assertInstanceOf(SemaphoreInterface::class, $semaphore);
+ $this->assertSame($keys[0], $keys[1]);
}
}