Coordinate editors with document locks
Enable expiring edit leases, control takeover access, and keep optimistic revisions as the final write fence.
Document locks coordinate authors who open the same collection document. An active lease makes the second editor’s form read-only and identifies the current owner; an authorized editor can take it over. Locks improve the authoring experience, but they do not grant update access and do not replace optimistic revision checks.
Enable locks
package content
import (
"time"
"github.com/riducms/ridu"
"github.com/riducms/ridu/field"
)
var Posts = ridu.Collection{
Slug: "posts",
LockDocuments: true,
DocumentLockConfig: ridu.DocumentLockConfig{
Duration: 5 * time.Minute,
},
Fields: []field.Definition{
field.Text("title", field.Required()),
},
}Zero duration uses five minutes. A custom duration must be at least ten seconds. Save this change
with ridu dev running; it regenerates contracts, safely synchronizes the development store, and
reloads the admin. The selected store must implement Ridu’s document-lock contract; all official
database adapters do. Before deployment, create, review, and verify the adapter migration.
What authors experience
When an authorized author opens an existing post, the admin acquires a persisted lease and refreshes it while the editor remains active. Leaving the route releases an owned lease; an abandoned lease expires after the configured duration.
If another author owns the active lease, the form becomes read-only and shows the owner’s label and expiry. Take over appears only when the current actor has unlock capability. A successful takeover replaces the previous lease; it does not save or discard either editor’s local form state.
Locking applies to existing collection documents. Create forms and globals do not acquire document leases.
Authorize takeover separately
Update access is required to acquire or refresh a lock. CollectionAccess.Unlock controls takeover
of another editor’s lease and falls back to Update when omitted. Define it when takeover should
be limited to a smaller role:
Access: ridu.CollectionAccess{
Update: canEditPosts,
Unlock: administratorsOnly,
},Reading lock state returns not-found behavior when the document itself is not readable, so lock metadata cannot reveal a hidden document. The server re-evaluates access for acquisition and takeover; showing or hiding the admin button is only presentation.
Use locks outside the admin
Custom authoring clients can use the generated SDK:
let state = await ridu.acquireDocumentLock('posts', post.id);
if (!state.owned && state.canTakeOver) {
state = await ridu.acquireDocumentLock('posts', post.id, true);
}
if (!state.owned) {
throw new Error(`This post is being edited by ${state.lock?.ownerLabel ?? 'another author'}.`);
}
try {
await ridu.update('posts', post.id, { title: 'Reviewed title' }, { revision: post._revision });
} finally {
await ridu.releaseDocumentLock('posts', post.id);
}Long-lived clients must refresh an owned lease before it expires. Reacquiring the same lock refreshes it. Browser unload delivery is best-effort, so expiry must remain the recovery path.
Always send the last observed _revision for versioned updates. A lock can expire, be taken over, or
be bypassed by a non-authoring client; the revision fence is what prevents a stale write from
overwriting a newer committed document.
Document locks are not account locks
An auth account can also be locked after repeated failed sign-ins. That is a separate authentication
feature controlled by AuthConfig.MaxLoginAttempts and AuthConfig.LockDuration. An authorized
administrator uses Force unlock or RiduClient.forceUnlock; document-lock takeover does not
change account state.
Troubleshooting
| Symptom | What to check |
|---|---|
| No lock appears | Confirm LockDocuments: true, keep ridu dev running, and open an existing collection document rather than a create form. |
| The form remains read-only | The lease belongs to another identity. Wait for expiry or ask an actor with Unlock access to take over. |
| Take over is missing | The actor lacks evaluated unlock capability, or the lease is already owned/expired. |
Lock calls return not_found |
The collection has no lock support, the document is absent, or read access hides it. |
Save still returns conflict |
Another committed write changed _revision. Refresh and reapply the intended edit; the lease is not a concurrency bypass. |
See Create and edit documents, Access control,
and the exact
RiduClient.acquireDocumentLock and
App.AcquireDocumentLock contracts.