[Lock] Include lock component in framework bundle #22113

Closed
wants to merge 3 commits into
from

Conversation

Projects
None yet
7 participants
@jderusse
Contributor

jderusse commented Mar 22, 2017

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets none
License MIT
Doc PR symfony/symfony-docs#8066

Usage

use the best available "out of box" store (semaphore if available, filesyste otherwise)

framework:
    lock: ~
    # lock: true
$this->get('lock')->acquire();
$this->get('lock.factory')->createLock('my resource')->acquire();

use a specific store

framework:
    lock: flock
    # lock: semaphore
    # lock: redis://localhost
    # lock: "%env(MEMCACHED_DSN)%"
    # lock: ["%env(REDIS_DSN_1)%", "%env(REDIS_DSN_2)%"]
$this->get('lock')->acquire();
$this->get('lock.factory')->createLock('my resource')->acquire();

use a named lock

framework:
    lock: 
        foo: flock
        bar: redis://localhost
$this->get('lock.foo')->acquire();
$this->get('lock.bar.factory')->createLock('my resource')->acquire();

factory usage

        <service id="acme" class="AppBundle\Acme">
            <argument type="service">
                <service class="Symfony\Component\Lock\Lock">
                    <factory service="lock.foo.factory" method="createLock" />
                    <argument>my resource</argument>
                    <argument>30</argument> <!-- optional TTL -->
                </service>
            </argument>
        </service>
  • Tests
+
+ <service id="lock.store.combined.abstract" class="Symfony\Component\Lock\Store\CombinedStore" abstract="true" public="false">
+ <argument /> <!-- List of stores -->
+ <argument type="service" id="lock.quorum.majority" /> <!-- Quorum -->

This comment has been minimized.

@jderusse

jderusse Mar 22, 2017

Contributor

Could be rename into strategy

@jderusse

jderusse Mar 22, 2017

Contributor

Could be rename into strategy

@jderusse jderusse changed the title from [Lock] Include lock component in framework bundle to [WIP] [Lock] Include lock component in framework bundle Mar 22, 2017

@fbourigault

This comment has been minimized.

Show comment
Hide comment
@fbourigault

fbourigault Mar 23, 2017

Contributor

What about adding a framework.lock.default config to override the lock.factory priority order? So the user can choose the implementation he wants as default.

Contributor

fbourigault commented Mar 23, 2017

What about adding a framework.lock.default config to override the lock.factory priority order? So the user can choose the implementation he wants as default.

@javiereguiluz

This comment has been minimized.

Show comment
Hide comment
@javiereguiluz

javiereguiluz Mar 23, 2017

Member

Maybe I'm late, but I'd like to propose a simpler way to use and configure this component inside the Symfony Framework. The idea, as usual, is to optimize/simplify the common case and don't complicate much the complex case.

Common case

Application defines/needs just 1 lock type.

Configuration

This is the default config, where Symfony picks the best lock type for you: semaphore if the extension is installed; flock otherwise:

framework:
    lock: ~

This is the explicit config where you set the lock type (string or array and some smart conversion by the Config component, as we do everywhere else):

framework:
    lock: 'flock'
    lock: 'semaphore'
    lock: 'memcached://m1.docker'
    lock: ['memcached://m1.docker', 'memcached://m2.docker']
    lock: 'redis://r1.docker'
    lock: ['redis://r1.docker', 'redis://r2.docker']

Usage

// non-blocking, non-expiring
$lock = $this->get('lock')->acquire();
// $lock = $container->get('lock')->acquire();

// blocking, non-expiring
$lock = $this->get('lock')->acquire(true);

// non-blocking, expiring in 60 seconds
$lock = $this->get('lock')->acquire(false, 60);

// normal operations on the lock
$lock->isAcquired();
$lock->refresh();
$lock->release();

Complex case

Application defines and uses several lock types.

Configuration

framework:
    lock:
        users: ['memcached://m1.docker', 'memcached://m2.docker']
        admin: 'flock'
        partners: 'redis://r1.docker'
        invoices: 'semaphore'

Usage

$adminLock = $this->get('lock.admin')->acquire();
$invoicesLock = $this->get('lock.invoices')->acquire(true);
$partnersLock = $this->get('lock.partners')->acquire(false, 30);
// ...
Member

javiereguiluz commented Mar 23, 2017

Maybe I'm late, but I'd like to propose a simpler way to use and configure this component inside the Symfony Framework. The idea, as usual, is to optimize/simplify the common case and don't complicate much the complex case.

Common case

Application defines/needs just 1 lock type.

Configuration

This is the default config, where Symfony picks the best lock type for you: semaphore if the extension is installed; flock otherwise:

framework:
    lock: ~

This is the explicit config where you set the lock type (string or array and some smart conversion by the Config component, as we do everywhere else):

framework:
    lock: 'flock'
    lock: 'semaphore'
    lock: 'memcached://m1.docker'
    lock: ['memcached://m1.docker', 'memcached://m2.docker']
    lock: 'redis://r1.docker'
    lock: ['redis://r1.docker', 'redis://r2.docker']

Usage

// non-blocking, non-expiring
$lock = $this->get('lock')->acquire();
// $lock = $container->get('lock')->acquire();

// blocking, non-expiring
$lock = $this->get('lock')->acquire(true);

// non-blocking, expiring in 60 seconds
$lock = $this->get('lock')->acquire(false, 60);

// normal operations on the lock
$lock->isAcquired();
$lock->refresh();
$lock->release();

Complex case

Application defines and uses several lock types.

Configuration

framework:
    lock:
        users: ['memcached://m1.docker', 'memcached://m2.docker']
        admin: 'flock'
        partners: 'redis://r1.docker'
        invoices: 'semaphore'

Usage

$adminLock = $this->get('lock.admin')->acquire();
$invoicesLock = $this->get('lock.invoices')->acquire(true);
$partnersLock = $this->get('lock.partners')->acquire(false, 30);
// ...
+
+ if (count($hostsDefinitions) > 1) {
+ $definition = new ChildDefinition('lock.store.combined.abstract');
+ $definition->replaceArgument(0, $hostsDefinitions);

This comment has been minimized.

@chalasr

chalasr Mar 23, 2017

Member

Would it make sense to lazy load stores using an iterator? It seems the combined store can break in the middle of the store chain. Btw, why not ChainStore instead of CombinedStore for consistency?

@chalasr

chalasr Mar 23, 2017

Member

Would it make sense to lazy load stores using an iterator? It seems the combined store can break in the middle of the store chain. Btw, why not ChainStore instead of CombinedStore for consistency?

+
+ if (null !== $username || null !== $password) {
+ if (!method_exists($client, 'setSaslAuthData')) {
+ trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.');

This comment has been minimized.

@ro0NL

ro0NL Mar 23, 2017

Contributor

What about a E_USER_WARNING? As we're clearly going to call an undefined method.

Edit: i see it's a copy paste of the cache component.. understandable. Probably not worth it then. Im not sure this is desirable maintenance-wise though (vs. soft-depending on symfony/cache).

@ro0NL

ro0NL Mar 23, 2017

Contributor

What about a E_USER_WARNING? As we're clearly going to call an undefined method.

Edit: i see it's a copy paste of the cache component.. understandable. Probably not worth it then. Im not sure this is desirable maintenance-wise though (vs. soft-depending on symfony/cache).

This comment has been minimized.

@jderusse

jderusse Mar 23, 2017

Contributor

I choose to use the same error/format than src/Symfony/Component/Cache/Traits/MemcachedTrait.php for more consistency

@jderusse

jderusse Mar 23, 2017

Contributor

I choose to use the same error/format than src/Symfony/Component/Cache/Traits/MemcachedTrait.php for more consistency

@nicolas-grekas nicolas-grekas added this to the 3.3 milestone Mar 24, 2017

@jderusse

This comment has been minimized.

Show comment
Hide comment
@jderusse

jderusse Apr 1, 2017

Contributor

@javiereguiluz Today I start to implement your suggestion (much simpler, I like it).
But then, I realize, it'll not be compatible with dynamic resources.
I suggest a small change in your proposal by adding factories too.

$this->get('lock_factory.invoices')->createLock('invoices.'.$invoice->getId());

the service lock.invoices would be an alias of $this->get('lock_factory.invoices')->createLock('invoices').
WDYT?

I've got some other question:

When you says $lock = $this->get('lock')->acquire(); you means $lock = $this->get('lock') + $isLocked = $this->get('lock')->acquire(); right?

Last point you are moving the ttl from the lock constructor to the acquire method. Is it made on purpose? Shouldn't it be a parameter defined in the config file like:

framework:
    lock:
        users: ['memcached://m1.docker', 'memcached://m2.docker']
        invoices:
            store: ['memcached://m1.docker', 'memcached://m2.docker']
            ttl: 300
Contributor

jderusse commented Apr 1, 2017

@javiereguiluz Today I start to implement your suggestion (much simpler, I like it).
But then, I realize, it'll not be compatible with dynamic resources.
I suggest a small change in your proposal by adding factories too.

$this->get('lock_factory.invoices')->createLock('invoices.'.$invoice->getId());

the service lock.invoices would be an alias of $this->get('lock_factory.invoices')->createLock('invoices').
WDYT?

I've got some other question:

When you says $lock = $this->get('lock')->acquire(); you means $lock = $this->get('lock') + $isLocked = $this->get('lock')->acquire(); right?

Last point you are moving the ttl from the lock constructor to the acquire method. Is it made on purpose? Shouldn't it be a parameter defined in the config file like:

framework:
    lock:
        users: ['memcached://m1.docker', 'memcached://m2.docker']
        invoices:
            store: ['memcached://m1.docker', 'memcached://m2.docker']
            ttl: 300
@nicolas-grekas

This comment has been minimized.

Show comment
Hide comment
@nicolas-grekas

nicolas-grekas Apr 28, 2017

Member

Moving to milestone 3.4 as this is not a blocker for 3.3. If you don't agree, please tell :)

Member

nicolas-grekas commented Apr 28, 2017

Moving to milestone 3.4 as this is not a blocker for 3.3. If you don't agree, please tell :)

@nicolas-grekas nicolas-grekas modified the milestones: 3.3, 3.4 Apr 28, 2017

@jderusse jderusse changed the base branch from master to 3.4 Jun 19, 2017

@jderusse jderusse changed the title from [WIP] [Lock] Include lock component in framework bundle to [Lock] Include lock component in framework bundle Jun 19, 2017

@jderusse jderusse referenced this pull request in symfony/symfony-docs Jun 19, 2017

Merged

[Lock] Integrate framework #8066

@jderusse

This comment has been minimized.

Show comment
Hide comment
@jderusse

jderusse Jul 31, 2017

Contributor

PR rebased

Contributor

jderusse commented Jul 31, 2017

PR rebased

+ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
+
+ <services>
+

This comment has been minimized.

@chalasr

chalasr Jul 31, 2017

Member

<defaults public="false" />

@chalasr

chalasr Jul 31, 2017

Member

<defaults public="false" />

This comment has been minimized.

@jderusse

jderusse Jul 31, 2017

Contributor

good catch

@jderusse

jderusse Jul 31, 2017

Contributor

good catch

+ if ('default' === $resourceName) {
+ $container->setAlias('lock.store', new Alias('lock.'.$resourceName.'.store'));
+ $container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory'));
+ $container->setAlias('lock', new Alias('lock.'.$resourceName));

This comment has been minimized.

@chalasr

chalasr Jul 31, 2017

Member

should be private unless strongly needed

@chalasr

chalasr Jul 31, 2017

Member

should be private unless strongly needed

This comment has been minimized.

@jderusse

jderusse Jul 31, 2017

Contributor

I moved .store services to private. But keep lock and lock.factory public. To let user retrieve the lock from a ContainerAware object (controller, command, ...)

$this->get('lock.foo')->acquire();
$this->get('lock.bar.factory')->createLock('my resource')->acquire();
$this->get('lock')->acquire();
$this->get('lock.factory')->createLock('my resource')->acquire();
@jderusse

jderusse Jul 31, 2017

Contributor

I moved .store services to private. But keep lock and lock.factory public. To let user retrieve the lock from a ContainerAware object (controller, command, ...)

$this->get('lock.foo')->acquire();
$this->get('lock.bar.factory')->createLock('my resource')->acquire();
$this->get('lock')->acquire();
$this->get('lock.factory')->createLock('my resource')->acquire();

This comment has been minimized.

@jderusse

jderusse Jul 31, 2017

Contributor

id I missed something? Or am I using it wrongly?

@jderusse

jderusse Jul 31, 2017

Contributor

id I missed something? Or am I using it wrongly?

This comment has been minimized.

@chalasr

chalasr Jul 31, 2017

Member

ContainerAware objects are still supported, but I think we all agree that they should not be promoted (for end applications esp.) and features should not be designed with that in mind.
Better inject @lock.factory (controllers/commands/everything as services, should be autoinjected quite easily also) rather than locate it using a DIC (here is the bad habit: a DIC is not meant to be used as a service locator but to wire services, see #21623 for reference).

If no internal need for get() this service, we should keep it private (regarding BC we can make it public afterwards if legit use case, not the inverse).

@chalasr

chalasr Jul 31, 2017

Member

ContainerAware objects are still supported, but I think we all agree that they should not be promoted (for end applications esp.) and features should not be designed with that in mind.
Better inject @lock.factory (controllers/commands/everything as services, should be autoinjected quite easily also) rather than locate it using a DIC (here is the bad habit: a DIC is not meant to be used as a service locator but to wire services, see #21623 for reference).

If no internal need for get() this service, we should keep it private (regarding BC we can make it public afterwards if legit use case, not the inverse).

+ // Generate factories for each resource
+ $factoryDefinition = new ChildDefinition('lock.factory.abstract');
+ $factoryDefinition->replaceArgument(0, new Reference('lock.'.$resourceName.'.store'));
+ $factoryDefinition->setPublic(true);

This comment has been minimized.

@chalasr

chalasr Jul 31, 2017

Member

unless strongly needed it should remain private

@chalasr

chalasr Jul 31, 2017

Member

unless strongly needed it should remain private

+ $combinedDefinition->replaceArgument(0, $storeDefinitions);
+ $container->setDefinition('lock.'.$resourceName.'.store', $combinedDefinition);
+ } else {
+ $container->setAlias('lock.'.$resourceName.'.store', new Alias((string) $storeDefinitions[0]));

This comment has been minimized.

@chalasr

chalasr Jul 31, 2017

Member

private?

@chalasr

chalasr Jul 31, 2017

Member

private?

+ $container->setDefinition($connectionDefinitionId, $connectionDefinition);
+ }
+
+ $storeDefinition = new Definition(\stdClass::class);

This comment has been minimized.

@chalasr

chalasr Jul 31, 2017

Member

StoreInterface::class?

@chalasr

chalasr Jul 31, 2017

Member

StoreInterface::class?

This comment has been minimized.

@jderusse

jderusse Jul 31, 2017

Contributor

indeed

@jderusse

jderusse Jul 31, 2017

Contributor

indeed

@chalasr

chalasr approved these changes Aug 9, 2017

with minor comment

+ * @param array $config
+ * @param ContainerBuilder $container
+ * @param XmlFileLoader $loader
+ */

This comment has been minimized.

@chalasr

chalasr Aug 9, 2017

Member

doesn't seem useful to me

@chalasr

chalasr Aug 9, 2017

Member

doesn't seem useful to me

This comment has been minimized.

@jderusse

jderusse Aug 9, 2017

Contributor

Agreed, but this is consistent with all other methods of this class.

@jderusse

jderusse Aug 9, 2017

Contributor

Agreed, but this is consistent with all other methods of this class.

This comment has been minimized.

@chalasr

chalasr Aug 9, 2017

Member

still, we should not add new ones. We have a lot of e.g. Constructor. docblock comments in the codebase, not worth removing them but we won't do the same for new constructors.

@chalasr

chalasr Aug 9, 2017

Member

still, we should not add new ones. We have a lot of e.g. Constructor. docblock comments in the codebase, not worth removing them but we won't do the same for new constructors.

This comment has been minimized.

@chalasr

chalasr Aug 9, 2017

Member

only some other did this mistake in fact, no consistency issue

@chalasr

chalasr Aug 9, 2017

Member

only some other did this mistake in fact, no consistency issue

@chalasr

This comment has been minimized.

Show comment
Hide comment
@chalasr

chalasr Aug 9, 2017

Member

@jderusse btw could you take a look at the the failing test on travis? It happens randomly and is unrelated to this PR, fixing it would be great

Member

chalasr commented Aug 9, 2017

@jderusse btw could you take a look at the the failing test on travis? It happens randomly and is unrelated to this PR, fixing it would be great

@jderusse

This comment has been minimized.

Show comment
Hide comment
@jderusse

jderusse Aug 10, 2017

Contributor

@chalasr tests should be fixed by #23847

Contributor

jderusse commented Aug 10, 2017

@chalasr tests should be fixed by #23847

@chalasr

This comment has been minimized.

Show comment
Hide comment
@chalasr

chalasr Aug 10, 2017

Member

Cool! thanks

Member

chalasr commented Aug 10, 2017

Cool! thanks

@chalasr

This comment has been minimized.

Show comment
Hide comment
Member

chalasr commented Aug 18, 2017

@fabpot

fabpot approved these changes Aug 23, 2017

+ {
+ $loader->load('lock.xml');
+
+ $container->getDefinition('lock.store.flock')->replaceArgument(0, sys_get_temp_dir());

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

This inlines the tempdir used at compile time for reuse at build time, making the dumped container not-independent from the build env.

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

This inlines the tempdir used at compile time for reuse at build time, making the dumped container not-independent from the build env.

This comment has been minimized.

@jderusse

jderusse Sep 5, 2017

Contributor

good catch

@jderusse

jderusse Sep 5, 2017

Contributor

good catch

+ $storeDefinition = new Reference('lock.store.semaphore');
+ break;
+ case $usedEnvs || preg_match('#^[a-z]++://#', $storeDsn):
+ if (!$container->hasDefinition($connectionDefinitionId = md5($storeDsn))) {

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

$container->hash() instead of md5

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

$container->hash() instead of md5

+ $container->setDefinition($connectionDefinitionId, $connectionDefinition);
+ }
+
+ $storeDefinition = new Definition(StoreInterface::class);

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

the definition should me made private

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

the definition should me made private

This comment has been minimized.

@jderusse

jderusse Sep 5, 2017

Contributor

fixed

@jderusse

jderusse Sep 5, 2017

Contributor

fixed

+ $storeDefinition->setFactory(array(StoreFactory::class, 'createStore'));
+ $storeDefinition->setArguments(array(new Reference($connectionDefinitionId)));
+
+ $container->setDefinition($storeDefinitionId = 'lock.'.$resourceName.'.store.'.md5($storeDsn), $storeDefinition);

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

$container->hash also here

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

$container->hash also here

+
+ $storeDefinition = new Reference($storeDefinitionId);
+ break;
+ case $usedEnvs:

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

dead code because of the previous case

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

dead code because of the previous case

+ $container->setDefinition('lock.'.$resourceName.'.factory', $factoryDefinition);
+
+ // Generate services for lock instances
+ $lockDefinition = new Definition(Lock::class);

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

should be private

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

should be private

This comment has been minimized.

@jderusse

jderusse Sep 5, 2017

Contributor

fixed

@jderusse

jderusse Sep 5, 2017

Contributor

fixed

+ if ('default' === $resourceName) {
+ $container->setAlias('lock.store', new Alias('lock.'.$resourceName.'.store', false));
+ $container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false));
+ $container->setAlias('lock', new Alias('lock.'.$resourceName, false));

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

missing FQCN aliases that could be use by autowiring

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

missing FQCN aliases that could be use by autowiring

This comment has been minimized.

@jderusse

jderusse Sep 5, 2017

Contributor

fixed

@jderusse

jderusse Sep 5, 2017

Contributor

fixed

+ *
+ * @throws \ErrorEception When invalid options or dsn are provided
+ */
+ public static function createConnection($dsn, array $options = array())

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

should be updated to match #23978

@nicolas-grekas

nicolas-grekas Sep 5, 2017

Member

should be updated to match #23978

+
+ <service id="lock.store.flock" class="Symfony\Component\Lock\Store\FlockStore">
+ <argument type="service">
+ <service class="string">

This comment has been minimized.

@jderusse

jderusse Sep 5, 2017

Contributor

I've some doublt about the value of class here

@jderusse

jderusse Sep 5, 2017

Contributor

I've some doublt about the value of class here

+ <service id="lock.store.flock" class="Symfony\Component\Lock\Store\FlockStore">
+ <argument type="service">
+ <service class="string">
+ <factory function="sys_get_temp_dir"/>

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 18, 2017

Member

instead of this, what about making the $lockPath arg of FlockStore optional, and make it use sys_get_temp_dir then?

@nicolas-grekas

nicolas-grekas Sep 18, 2017

Member

instead of this, what about making the $lockPath arg of FlockStore optional, and make it use sys_get_temp_dir then?

+ </argument>
+ </service>
+
+ <service id="lock.store.semaphore" class="Symfony\Component\Lock\Store\SemaphoreStore"/>

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 18, 2017

Member

bad consistency about space before /> in the file

@nicolas-grekas

nicolas-grekas Sep 18, 2017

Member

bad consistency about space before /> in the file

+ *
+ * @return \Redis|\Predis\Client According to the "class" option
+ */
+ public static function createConnection($dsn, array $options = array())

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 18, 2017

Member

We could maybe consider a new component, named Dsn, with factories for any kind of DSN we want to support?
not sure we can make it for 3.4, but what do others think about the idea?

@nicolas-grekas

nicolas-grekas Sep 18, 2017

Member

We could maybe consider a new component, named Dsn, with factories for any kind of DSN we want to support?
not sure we can make it for 3.4, but what do others think about the idea?

@nicolas-grekas

👍

@@ -32,12 +32,15 @@ class FlockStore implements StoreInterface
private $lockPath;
/**
- * @param string $lockPath the directory to store the lock
+ * @param string|null $lockPath the directory to store the lock. Default values will use temporary directory

This comment has been minimized.

@nicolas-grekas

nicolas-grekas Sep 19, 2017

Member

the directory to store the lock, defaults to the system's temporary directory

@nicolas-grekas

nicolas-grekas Sep 19, 2017

Member

the directory to store the lock, defaults to the system's temporary directory

@chalasr

fine tuning

+ public static function createConnection($dsn, array $options = array())
+ {
+ if (!is_string($dsn)) {
+ throw new InvalidArgumentException(sprintf('The %s() method expect argument #1 to be string, %s given.', __METHOD__, gettype($dsn)));

This comment has been minimized.

@chalasr

chalasr Sep 26, 2017

Member

expects

@chalasr

chalasr Sep 26, 2017

Member

expects

+ */
+class StoreFactory
+{
+ public static function createConnection($dsn, array $options = array())

This comment has been minimized.

@chalasr

chalasr Sep 26, 2017

Member

I think we should add a docblock listing supported dsn

@chalasr

chalasr Sep 26, 2017

Member

I think we should add a docblock listing supported dsn

This comment has been minimized.

@jderusse

jderusse Sep 27, 2017

Contributor

will be removed replaced by the new Dns component

@jderusse

jderusse Sep 27, 2017

Contributor

will be removed replaced by the new Dns component

+ throw new InvalidArgumentException(sprintf('Unsupported DSN: %s.', $dsn));
+ }
+
+ public static function createStore($connection)

This comment has been minimized.

@chalasr

chalasr Sep 26, 2017

Member

same

@param \Redis|\RedisArray|\RedisCluster|\Predis\Client|\Memcached $connection
@return RedisStore|MemcachedStore
@chalasr

chalasr Sep 26, 2017

Member

same

@param \Redis|\RedisArray|\RedisCluster|\Predis\Client|\Memcached $connection
@return RedisStore|MemcachedStore

jderusse added some commits Jan 29, 2017

@fabpot

fabpot approved these changes Sep 27, 2017

@fabpot

This comment has been minimized.

Show comment
Hide comment
@fabpot

fabpot Sep 27, 2017

Member

Thank you @jderusse.

Member

fabpot commented Sep 27, 2017

Thank you @jderusse.

@fabpot fabpot closed this Sep 27, 2017

fabpot added a commit that referenced this pull request Sep 27, 2017

feature #22113 [Lock] Include lock component in framework bundle (jde…
…russe)

This PR was squashed before being merged into the 3.4 branch (closes #22113).

Discussion
----------

[Lock] Include lock component in framework bundle

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | none
| License       | MIT
| Doc PR        | symfony/symfony-docs#8066

## Usage

use the best available "out of box" store (semaphore if available, filesyste otherwise)
```yml
framework:
    lock: ~
    # lock: true
```

```php
$this->get('lock')->acquire();
$this->get('lock.factory')->createLock('my resource')->acquire();
```

use a specific store
```yml
framework:
    lock: flock
    # lock: semaphore
    # lock: redis://localhost
    # lock: "%env(MEMCACHED_DSN)%"
    # lock: ["%env(REDIS_DSN_1)%", "%env(REDIS_DSN_2)%"]
```

```php
$this->get('lock')->acquire();
$this->get('lock.factory')->createLock('my resource')->acquire();
```

use a named lock
```yml
framework:
    lock:
        foo: flock
        bar: redis://localhost
```

```php
$this->get('lock.foo')->acquire();
$this->get('lock.bar.factory')->createLock('my resource')->acquire();
```

factory usage

```xml
        <service id="acme" class="AppBundle\Acme">
            <argument type="service">
                <service class="Symfony\Component\Lock\Lock">
                    <factory service="lock.foo.factory" method="createLock" />
                    <argument>my resource</argument>
                    <argument>30</argument> <!-- optional TTL -->
                </service>
            </argument>
        </service>
```

* [x] Tests

Commits
-------

b4b00c9 [Lock] Include lock component in framework bundle

@fabpot fabpot referenced this pull request Oct 18, 2017

Merged

Release v3.4.0-BETA1 #24609

@fabpot fabpot referenced this pull request Oct 19, 2017

Merged

Release v4.0.0-BETA1 #24612

javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Jan 29, 2018

minor #8066 [Lock] Integrate framework (jderusse, javiereguiluz)
This PR was merged into the 3.4 branch.

Discussion
----------

[Lock] Integrate framework

Should probably be merged after #7866
Documentation for symfony/symfony#22113

Commits
-------

142e703 Fixed minor issues
7f1e087 Add lock configuration in framework bundle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment