Lock storage backends¶
The optional webdav_lock_pdo submodule moves WebDAV lock storage
from the default tempdir file into the site's database, so locks
survive container restarts.
Without this submodule, the sabre/dav locking plugin writes every
lock to a single serialized file at
getTempDirectory() . '/webdav/locks.data'. That file is fast and
zero-config, but on containerized deployments it evaporates with
the container — every active LOCK is dropped on restart and the
desktop client receives 409 Conflict on its next UNLOCK. With
webdav_lock_pdo enabled, every LOCK / UNLOCK goes through a
DB-backed sabre backend (Sabre\DAV\Locks\Backend\PDO) pointed at
the same Drupal connection the rest of the site uses, so lock state
is durable across container / host restarts.
When to enable¶
Enable webdav_lock_pdo when:
- The site runs in containers and locks need to survive restarts.
- Multiple PHP workers serve
/webdav/and you want them to see a consistent lock view through transactional reads / writes rather than the file-backend's advisoryflock. - You want the lock state to live next to the rest of your application state (single backup, single failover story).
Skip it when:
- The deployment is a single long-running host where the temp directory persists naturally. The file backend has zero overhead and one fewer table to maintain.
- The site has heavy LOCK churn and DB load is already a concern — every LOCK / UNLOCK adds a row write.
Setup¶
drush en webdav_lock_pdo -y
Enable creates the webdav_locks table (see webdav_lock_pdo.install).
From the next request onward, every LOCK / UNLOCK hits the database;
the previous file-based store is left in place but no longer
written to (it can be removed manually). The admin page at
/admin/reports/webdav-locks keeps working — its
LockManagerInterface consumer transparently routes to the new
backend's introspection implementation.
No further config: the submodule reuses Drupal's active
Connection, so the lock backend lives in the same database as the
rest of the site, honors the same db prefix, and participates in
the same backup / replication / migration tooling.
Switching back¶
To return to the file backend:
drush pmu webdav_lock_pdo -y
The schema is dropped on uninstall. Any locks held in the database
at uninstall time are lost; if active edits matter, wait for clients
to release before flipping. Reverting works because both backends
implement the same sabre BackendInterface and the same
Drupal\webdav\Locks\LockManagerInterface; the only state that
crosses backends is the active lock list, which is intentionally
ephemeral.
What happens behind the scenes¶
webdav_lock_pdo.services.yml decorates two services:
webdav.lock_backend— sabre'sBackendInterface, consumed bySabre\DAV\Locks\Pluginduring LOCK / UNLOCK. The decorator replaces the file-backed factory output withSabre\DAV\Locks\Backend\PDOpointed at the active DrupalConnection's underlying\PDOinstance.webdav.lock_manager— the admin-side read interface (LockManagerInterface). The decorator replaces the file-readingLockManagerwithPdoLockManager, which runsSELECT/DELETEagainst the samewebdav_lockstable that the sabre backend writes to.
Decoration of both sides as a pair is deliberate: a single decoration on either alone would split lock visibility (sabre writes to one store, admin reads from another). The submodule keeps the two halves in lockstep.
Schema¶
The webdav_locks table matches sabre's PDO backend schema
verbatim — sabre writes literal SQL against the column names, so
they cannot be renamed:
| Column | Type | Notes |
|---|---|---|
id |
serial PK | Surrogate primary key. |
owner |
varchar(100) | Lock owner from the LOCK request body. |
timeout |
int unsigned | Lock timeout in seconds. |
created |
int | Lock creation Unix timestamp. |
token |
varchar(100) | Opaque sabre lock token (indexed). |
scope |
tinyint | 1 = exclusive, 2 = shared. |
depth |
tinyint | 0 = single resource, 1 = infinite. |
uri |
varchar(1000) | Resource URI (prefix-indexed at 100 chars). |
Drupal's standard db prefix applies on top of webdav_locks if
configured.
Custom backends¶
Want a Memcached / Redis / external-lock-service backend instead
of PDO? The seam is the webdav.lock_backend service plus the
Drupal\webdav\Locks\LockManagerInterface alias. Register your
own implementations and decorate the two services as a pair — the
webdav_lock_pdo submodule is the worked example. The audit-event
dispatch (WebDavEvents::LOCK_ACQUIRED, LOCK_RELEASED,
LOCK_FORCE_RELEASED) lives in the sabre plugin layer and is
backend-agnostic, so swapping backends does not break audit trail
integration.