Skip to content

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 advisory flock.
  • 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's BackendInterface, consumed by Sabre\DAV\Locks\Plugin during LOCK / UNLOCK. The decorator replaces the file-backed factory output with Sabre\DAV\Locks\Backend\PDO pointed at the active Drupal Connection's underlying \PDO instance.
  • webdav.lock_manager — the admin-side read interface (LockManagerInterface). The decorator replaces the file-reading LockManager with PdoLockManager, which runs SELECT / DELETE against the same webdav_locks table 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.