8000 Add docs for the Lock component by jderusse · Pull Request #7364 · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content

Add docs for the Lock component #7364

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 24, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix typo
  • Loading branch information
jderusse committed Feb 17, 2017
commit 60bfe032ceaf2f5c158dd68167f2332f0f7ffe12
62 changes: 28 additions & 34 deletions components/lock.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
The Lock Component
====================
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many ==


The Lock Component provides a mechanism to garentee an exclusive access into
a critical section. The component ships with ready to use stores for the
most common backends.
The Lock Component provides a mechanism to guarantee an exclusive access
into a critical section. The component ships with ready to use stores for
the most common backends.

.. versionadded:: 3.3
The Lock component was introduced in Symfony 3.3.
Expand All @@ -22,17 +22,16 @@ You can install the component in 2 different ways:

.. include:: /components/require_autoload.rst.inc


Usage
-----

In order to centralize state of locks, you first need to create a ``Store``.
Then, you can ask to this store to create a Lock for your ``resource``.

The :method:`Symfony\\Component\\Lock\\LockInterface::acquire` method tries to
acquire the lock. If the lock is can not be acquired, the method throws a
acquire the lock. If the lock can not be acquired, the method throws a
:class:`Symfony\\Component\\Lock\\Exception\\LockConflictedException`. You can
safly call the ``acquire()`` method several time, even if you already acquired
safely call the ``acquire()`` method several times, even if you already acquired
it.

.. code-block:: php
Expand All @@ -41,30 +40,30 @@ it.
use Symfony\Component\Lock\Exception\LockConflictedException;

$store = new SemaphoreStore();
$lock = $store->createLock('hello');
$lock = $store->createLock('invoice-pdf-generation');

try {
$lock->acquire();
// the resource "hello" is locked. You can perform your task safely.
// the resource "invoice-pdf-generation" is locked.

// do whatever you want.
// You can compute and generate invoice safely here.

$lock->release();
} catch (LockConflictedException $e) {
// the resource "hello" is already locked by another process
// the resource "invoice-pdf-generation" is already locked by another process
}

The first argument of `createLock` is a string representation of the
The first argument of ``createLock`` is a string representation of the
``resource`` to lock.

.. note::

In opposition to some other implementations, the Lock Component distinguish
locks instances, even when they are created from the same ``resource``.
In opposition to some other implementations, the Lock Component
distinguishes locks instances, even when they are created from the same
``resource``.
If you want to share a lock in several services. You have to share the
instance of Lock returned by the ``Store::createLock`` method.


Blocking locks
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing cap to locks

--------------

Expand All @@ -73,7 +72,7 @@ You can pass an optional blocking argument as the first argument to the
defaults to ``false``. If this is set to ``true``, your PHP code will wait
infinitely until the lock is released by another process.

Some ``Store`` (but not all) natively supports this features. When they don't,
Some ``Store`` (but not all) natively supports this feature. When they don't,
you can decorate it with the ``RetryTillSaveStore``.

.. code-block:: php
Expand All @@ -84,20 +83,17 @@ you can decorate it with the ``RetryTillSaveStore``.
$store = new RedisStore(new \Predis\Client('tcp://localhost:6379'));
$store = new RetryTillSaveStore($store);

$lock = $store->createLock('hello');
$lock = $store->createLock('notification-flush');

$lock->acquire(true);



Expirable Locks
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some doubts about the Expirable word. "Official" dictionaries don't include it, but Internet dictionaries include it. In any case, after reading this discussion maybe it's a good idea to rename it to Expiring Locks.

The key is that "expirable lock" means "it can expire" (maybe it will expire or maybe it will not) whereas "expiring lock" means "it will expire" (it's 100% sure that this lock will expire).

---------------
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra -


Working with a remote ``Store`` is hard. In oposition to local ``Stores``
(like :ref:`FlockStore <lock-store-flock>` or :ref:`SemaphoreStore <lock-store-semaphore>`) there is now way for the remote
``Store`` to know whether or not the locker process is till alive. Due tu bugs,
fatal errors or segmentation fault, we can't garentee that the ``release()``
function will be called, which would cause a ``resource`` to be locked
Working with a remote ``Store`` is hard. There is now way for the remote
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no way?

``Store`` to know if the locker process is till alive.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still?

Due to bugs, fatal errors or segmentation fault, we can't guarantee that the
``release()`` method will be called, which would cause a ``resource`` to be locked
infinitely.

To fill this gap, the remote ``Stores`` provide an expirable mechanism: The lock
Expand All @@ -106,9 +102,9 @@ When the timeout occured, the lock is automatically released even if the locker
don't call the ``release()`` method.

That's why, when you create a lock on an expirable ``Store``. You have to choose
carrefully the correct TTL. When too low, you take the risk to "loose" the lock
(and someone else acquire it) wheras you don't finish your task.
When too hight and the process crash before you call the ``release()`` method,
carefully the correct TTL. When too low, you take the risk to "lose" the lock
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loose

(and someone else acquire it) whereas you don't finish your task.
When too high and the process crash before you call the ``release()`` method,
the ``resource`` will stay lock till the timeout.


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra blank line

Expand All @@ -118,7 +114,7 @@ the ``resource`` will stay lock till the timeout.

$store = new RedisStore(new \Predis\Client('tcp://localhost:6379'));

$lock = $store->createLock('hello', 30);
$lock = $store->createLock('charts-generation', 30);

$lock->acquire();
try {
Expand All @@ -129,12 +125,11 @@ the ``resource`` will stay lock till the timeout.

.. tip::

To avoid to let the Lock in a locking state, try to always release an
To avoid letting the Lock in a locking state, try to always release an
expirable lock by wraping the job in a try/catch block for instance.


When you have to work on a really long task, you should not set the TTL to
overlaps the duration of this task. Instead, the Lock Component expose a
overlap the duration of this task. Instead, the Lock Component expose a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exposes

:method:`Symfony\\Component\\Lock\\LockInterface::refresh` method in order to
put off the TTL of the Lock. Thereby you can choose a small initial TTL, and
regulary refresh the lock
Expand All @@ -145,7 +140,7 @@ regulary refresh the lock

$store = new RedisStore(new \Predis\Client('tcp://localhost:6379'));

$lock = $store->createLock('hello', 30);
$lock = $store->createLock('charts-generation', 30);

$lock->acquire();
try {
Expand All @@ -159,14 +154,13 @@ regulary refresh the lock
$lock->release()
}


Available Stores
----------------

``Stores`` are classes that implement :class:`Symfony\\Component\\Lock\\StoreInterface`.
This component provides several adapters ready to use in your applications.

Here is a small summary of availanble ``Stores`` and theire capabilities.
Here is a small summary of available ``Stores`` and their capabilities.

+----------------------------------------------+--------+----------+-----------+
| Store | Scope | Blocking | Expirable |
Expand Down Expand Up @@ -289,7 +283,7 @@ result, uses a quorum to decide whether or not the lock is acquired.

This ``Store`` is usefull for High availability application. You can provide
several Redis Server, and use theses server to manage the Lock. A
MajorityQuorum is enougth to safly acquire a lock while it allow some Redis
MajorityQuorum is enougth to safely acquire a lock while it allow some Redis
server failure.

.. code-block:: php
Expand Down
0