IXarlie Mutex Bundle
[][GA Link]
, (*1)
This bundle integrates the symfony/lock
capabilities into kernel.controller
events., (*2)
For previous releases with arvenil/ninja-mutex
dependency follow the version 1, (*3)
Before continuing, please read the following links for more information.
- Symfony/Lock
- Concurrency with Locks, (*4)
Install
composer require ixarlie/mutex-bundle "^2.1"
Add the bundle in the kernel class:, (*5)
$bundles = [
// ...
IXarlie\MutexBundle\IXarlieMutexBundle::class => ['all' => true],
// ...
];
Configuration
# Symfony lock configuration
framework:
lock:
main: flock
alt: semaphore
i_xarlie_mutex:
# Add the Symfony lock factories services id
factories:
- 'lock.default.factory'
- 'lock.main.factory'
- 'lock.alt.factory'
Locking Strategy
This bundle ships 3 different locking strategies:, (*6)
-
block
(BlockLockingStrategy
), (*7)
It attempts to acquire the lock. If the lock is already acquired then an exception is thrown. This strategy does
not block until the release of the lock., (*8)
-
force
(ForceLockingStrategy
), (*9)
It acquires the lock. Whether the lock is acquired, it forces a release before acquire it., (*10)
-
queue
(QueueLockingStrategy
), (*11)
It attempts to acquire the lock. Whether the lock is acquired, this strategy will wait until the release of the lock.
The queue
strategy will work depending on the service
configuration., (*12)
Read Blocking
section in Symfony Docs, (*13)
You can implement your own LockingStrategy
classes. Use the tag ixarlie_mutex.strategy
in your services to register
them in the LockExecutor
service., (*14)
services:
app.mutex_locking_strategy:
class: App\Mutex\LockingStrategy
tags:
- { name: ixarlie_mutex.strategy }
Naming Strategy
The name
option is not required in the annotation. However, a name is mandatory in order to create a LockInterface
instance., (*15)
This bundle ships 2 naming strategies:, (*16)
-
DefaultNamingStrategy
, if a name
is not set in the annotation, this class will use the request information.
-
UserIsolationNamingStrategy
, if the userIsolation
is enabled, this class will append the token user information
to the name
value. It decorates DefaultNamingStrategy
.
You can implement your own NamingStrategy
., (*17)
- Decorating
ixarlie_mutex.naming_strategy
(recommended)
services:
app.mutex_naming_strategy:
class: App\Mutex\NamingStrategy
decorates: 'ixarlie_mutex.naming_strategy'
arguments: ['app.mutex_naming_strategy.inner']
- Replacing the alias definition
ixarlie_mutex.naming_strategy
with your own service id. This will execute only your
logic.
services:
app.mutex_naming_strategy:
class: App\Mutex\NamingStrategy
ixarlie_mutex.naming_strategy:
alias: app.mutex_naming_strategy
Annotation
The MutexRequest
annotation can be used only on controller methods., (*18)
Options
The lock factory service name. It should be one of the services listed in the factories
setting., (*19)
Examples:, (*20)
framework:
lock: semaphore
i_xarlie_mutex:
factories:
- 'lock.default.factory'
```php, (*21)
[MutexRequest(service: 'lock.default.factory')]
```yaml
framework:
lock:
main_lock: flock
secondary_lock: semaphore
i_xarlie_mutex:
factories:
- 'lock.main_lock.factory'
```php, (*22)
[MutexRequest(service: 'lock.main_lock.factory')]
- `strategy` (required)
One of the registered locking strategies. Read the `Locking Strategy` section.
Examples:
```php
#[MutexRequest(service: 'lock.default.factory', strategy: 'block')]
#[MutexRequest(service: 'lock.default.factory', strategy: 'queue')]
#[MutexRequest(service: 'lock.default.factory', strategy: 'force')]
The lock's name. If no name is provided, the name will be generated using the registered naming strategies., (*23)
Note: Read userIsolation
option to know how it affects to the name., (*24)
Note: The prefix ixarlie_mutex_
is prefixed to the name., (*25)
Note: The naming strategy output is md5 hashed to avoid any issue with some PersistingStoreInterface implementations., (*26)
Examples:, (*27)
#[MutexRequest(service: 'lock.default.factory', strategy: 'block')]
#[MutexRequest(service: 'lock.default.factory', strategy: 'block', name: 'lock_name')]
This is a custom message for the exception in case the lock cannot be acquired., (*28)
Examples:, (*29)
#[MutexRequest(service: 'lock.default.factory', strategy: 'block', message: 'Busy!')]
-
userIsolation
(optional, default: false)
This option will add token user context to the name
option in order to have isolated locks for different users., (*30)
Example:, (*31)
#[MutexRequest(service: 'lock.default.factory', strategy: 'block', userIsolation: true)]
Note: If security.token_storage
is not available and userIsolation
is set to true, an exception will be thrown., (*32)
Note: Be aware about using userIsolation
in anonymous routes., (*33)
Maximum expected lock duration in seconds., (*34)
Example:, (*35)
use IXarlie\MutexBundle\MutexRequest;
class MyController {
#[MutexRequest(
service: 'lock.default.factory',
strategy: 'block',
name: 'action_name',
userIsolation: true,
message: 'Busy!',
ttl: 20.0
)]
public function foo()
{
return [];
}
}