Skip to content

Commit bbeecfe

Browse files
committed
Add locking documentation
1 parent 5756f27 commit bbeecfe

File tree

7 files changed

+193
-0
lines changed

7 files changed

+193
-0
lines changed

.vitepress/toc_en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@
185185
"items": [
186186
{ "text": "Events", "link": "/core-libraries/events" },
187187
{ "text": "Caching", "link": "/core-libraries/caching" },
188+
{ "text": "Locking", "link": "/core-libraries/locking" },
188189
{ "text": "Email", "link": "/core-libraries/email" },
189190
{ "text": "Logging", "link": "/core-libraries/logging" },
190191
{ "text": "Security", "link": "/core-libraries/security" },

docs/en/contents.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
- [Error & Exception Handling](development/errors)
3333
- [Events System](core-libraries/events)
3434
- [Internationalization & Localization](core-libraries/internationalization-and-localization)
35+
- [Locking](core-libraries/locking)
3536
- [Logging](core-libraries/logging)
3637
- [Modelless Forms](core-libraries/form)
3738
- [Pagination](controllers/pagination)

docs/en/core-libraries/locking.md

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# Locking
2+
3+
`class` Cake\Lock\**Lock**
4+
5+
Locking helps you coordinate access to shared resources across concurrent
6+
requests, CLI commands, queue workers, or background jobs. Use locks when you
7+
need to ensure that only one process performs a critical section at a time.
8+
9+
CakePHP provides the `Cake\Lock\Lock` facade together with pluggable lock
10+
engines for Redis, Memcached, local files, and no-op/testing usage.
11+
12+
## Configuring Lock Engines
13+
14+
Lock engine configurations are typically defined in **config/app.php**:
15+
16+
```php
17+
'Lock' => [
18+
'default' => [
19+
'className' => 'Redis',
20+
'host' => '127.0.0.1',
21+
'port' => 6379,
22+
'prefix' => 'myapp_lock_',
23+
'ttl' => 60,
24+
],
25+
],
26+
```
27+
28+
You can also configure lock engines at runtime:
29+
30+
```php
31+
use Cake\Lock\Lock;
32+
33+
Lock::setConfig('orders', [
34+
'className' => 'Redis',
35+
'host' => '127.0.0.1',
36+
'port' => 6379,
37+
'prefix' => 'orders_',
38+
'ttl' => 30,
39+
]);
40+
```
41+
42+
Lock configurations use the same `className` conventions as other registry-based
43+
CakePHP services:
44+
45+
```php
46+
Lock::setConfig('default', ['className' => 'Redis']);
47+
Lock::setConfig('default', ['className' => 'Cake\Lock\Engine\RedisLockEngine']);
48+
```
49+
50+
If an engine cannot be initialized, CakePHP falls back to the noop
51+
`NullLockEngine` and emits a warning.
52+
53+
## Acquiring and Releasing Locks
54+
55+
Use `Lock::acquire()` to attempt a non-blocking lock:
56+
57+
```php
58+
use Cake\Lock\Lock;
59+
60+
$lock = Lock::acquire('invoice-' . $invoiceId, ttl: 60);
61+
if ($lock === null) {
62+
return;
63+
}
64+
65+
try {
66+
$this->Invoices->send($invoiceId);
67+
} finally {
68+
$lock->release();
69+
}
70+
```
71+
72+
The returned `AcquiredLock` object represents the held lock. You can:
73+
74+
- call `release()` to release it explicitly
75+
- call `refresh()` to extend the TTL for long-running work
76+
- rely on its best-effort destructor cleanup if the handle is dropped
77+
78+
Explicit release is still recommended for predictable behavior.
79+
80+
## Preferred Usage with `synchronized()`
81+
82+
In many cases, `Lock::synchronized()` is the simplest and safest API because it
83+
guarantees prompt release:
84+
85+
```php
86+
$result = Lock::synchronized(
87+
'reports-daily',
88+
function () {
89+
return $this->Reports->buildDaily();
90+
},
91+
ttl: 120,
92+
timeout: 10,
93+
);
94+
```
95+
96+
If the lock cannot be acquired before the timeout expires, `synchronized()`
97+
returns `null`.
98+
99+
## Blocking Acquisition
100+
101+
Use `Lock::acquireBlocking()` when you want to wait for a lock to become
102+
available:
103+
104+
```php
105+
$lock = Lock::acquireBlocking(
106+
'payment-' . $paymentId,
107+
ttl: 60,
108+
timeout: 10,
109+
retryInterval: 100,
110+
);
111+
112+
if ($lock === null) {
113+
return;
114+
}
115+
116+
try {
117+
$this->Payments->capture($paymentId);
118+
} finally {
119+
$lock->release();
120+
}
121+
```
122+
123+
The `retryInterval` value is expressed in milliseconds.
124+
125+
## Inspecting and Managing Locks
126+
127+
CakePHP provides additional helper methods for lock lifecycle management:
128+
129+
```php
130+
if (Lock::isLocked('imports-products')) {
131+
return;
132+
}
133+
134+
$lock = Lock::acquire('imports-products');
135+
136+
if ($lock) {
137+
$lock->refresh(120);
138+
$lock->release();
139+
}
140+
141+
Lock::forceRelease('imports-products');
142+
```
143+
144+
- `isLocked()` performs a point-in-time check using the underlying engine
145+
- `refresh()` extends the lock TTL if the current owner still holds the lock
146+
- `forceRelease()` bypasses ownership checks and should only be used for
147+
administrative recovery flows
148+
149+
## Available Engines
150+
151+
CakePHP ships with the following lock engines:
152+
153+
- `Redis` Recommended for distributed systems and multi-node deployments
154+
- `Memcached` Suitable when Memcached is already part of your infrastructure
155+
- `File` Useful for single-server deployments using local filesystem locks
156+
- `Null` Useful for tests, local development, and intentional no-op behavior
157+
158+
### Shared Engine Options
159+
160+
All lock engines support these common options:
161+
162+
- `prefix` Prefix added to lock keys
163+
- `ttl` Default lock time-to-live in seconds
164+
165+
### RedisLockEngine Options
166+
167+
- `host` Redis server host
168+
- `port` Redis server port
169+
- `password` Redis password
170+
- `database` Redis database index
171+
- `timeout` Connection timeout
172+
- `persistent` Whether to use persistent connections
173+
174+
### MemcachedLockEngine Options
175+
176+
- `servers` Array of Memcached servers
177+
- `persistent` Persistent connection identifier
178+
179+
### FileLockEngine Options
180+
181+
- `path` Directory used to store lock files
182+
183+
The `FileLockEngine` is local to a single host. Unlike Redis or Memcached, it
184+
does not provide true TTL-based expiration in the backend. Locks are normally
185+
released explicitly, when the lock handle is destroyed, or when the process
186+
terminates.

docs/en/epub-contents.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [Views](views)
1414
- [Database Access & ORM](orm)
1515
- [Caching](core-libraries/caching)
16+
- [Locking](core-libraries/locking)
1617
- [Bake Console](bake)
1718
- [Console Commands](console-commands)
1819
- [Debugging](development/debugging)

docs/en/intro.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ features in CakePHP are:
155155

156156
- A [caching](core-libraries/caching) framework that integrates with
157157
Memcached, Redis and other backends.
158+
- A [locking](core-libraries/locking) API for coordinating critical sections
159+
across concurrent requests, workers, and commands.
158160
- Powerful [code generation tools](bake/usage) so you can start immediately.
159161
- [Integrated testing framework](development/testing) so you can ensure
160162
your code works perfectly.

docs/en/pdf-contents.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [Views](views)
1414
- [Database Access & ORM](orm)
1515
- [Caching](core-libraries/caching)
16+
- [Locking](core-libraries/locking)
1617
- [Bake Console](bake)
1718
- [Console Commands](console-commands)
1819
- [Debugging](development/debugging)

docs/en/topics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Introduction to all the key parts of CakePHP:
2424
- [Entities](orm/entities)
2525
- [Error & Exception Handling](development/errors)
2626
- [Caching](core-libraries/caching)
27+
- [Locking](core-libraries/locking)
2728
- [Logging](core-libraries/logging)
2829
- [Modelless Forms](core-libraries/form)
2930
- [Sessions](development/sessions)

0 commit comments

Comments
 (0)