4.3 KiB
4.3 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | |||
|---|---|---|---|---|---|---|---|---|---|---|---|
| pg-engine-locks | Postgres engine — named locks (`try_lock`, `Lock` handle, duration guards) | pending |
|
narrow | low | component | implementation |
|
Description
Implement the named-lock mechanism's pg arm — the smallest mechanism, and the one with the strongest POC ground (the pg POC's lock probe pinned acquire/release/renew with TTL and expiry re-acquisition directly). Over the schema task's locks table:
try_lock(name, owner, ttl)— shared-namespace + non-empty owner validation (InvalidName); the duration guard (ttl <= 0→ opaqueErr(Database), detail in the source chain — ADR-023 §2's duration kind; an exclusion mechanism must not silently hand back a lease the caller believes it holds); the closed-store check; then the acquire op on a pool connection: opportunistic-expiry- delete + insert-or-reacquire + read-back (the substrate'slock_acquiresemantics, re-derived — the POC's probe shape).Ok(None)= held elsewhere (no-work is a value);Ok(Some(boxed Lock))on grant.Lockhandle (renew, consumingrelease):renew(ttl)— the same duration guard; the new full TTL window from now (not additive);false= lost it (expired and re-acquired by another owner — the owner-scoped update's 0-rows).release(self: Box<Self>)— consuming; the owner-scoped delete;true= was held (row gone by this owner's hand),false= row-less or foreign (the substrate's row-scoped truth-teller posture — no handle-local "held" flag caching).
- Guarantee row posture (ADR-008 §7): mutual exclusion bounded by TTL + renewal; expiry lapses silently (no revocation event — expired rows are deleted opportunistically by the next acquire's expiry-delete, no general expiry sweeper — the inherited posture, documented); re-acquirable after expiry (the POC-pinned property — pin it engine-side here; the contract-suite row remains for the suite itself).
- Same-owner re-acquire: pin the inherited disposition (the substrate's shape: the same owner's re-acquire keeps the original row, TTL not refreshed, reports granted — the SQLite task's pinned posture; engine-sqlite.md's mapping row calls it inherited deliberately, and the pg arm should match it for cross-engine equivalence — flag in Notes if the pg realization differs).
- Post-lapse release arms: pin both (the stale holder's release
deletes its own stale row →
true; after a foreign re-acquire →false) — the SQLite task's pinned shape, matched here. - Closed-store posture:
try_lock/renew/releasefail closed with opaqueDatabase(the engine-wide shape). - No
lock_tx— deliberate absence (core-contract.md's named- locks section); nothing to build, just don't invent one.
Acceptance Criteria
try_lock: validation (name + owner), duration guard (ttl <= 0→ opaqueErr, detail in the source chain), closed-store check, then acquire —Ok(None)on held-elsewhere- Exclusion + loser shape pinned (two owners, one wins); expiry re-acquisition pinned (the POC's property, engine-side)
renew: duration guard; full-window reset;falseon lost/expired-and-reacquiredrelease: consuming, owner-scoped, both boolean arms pinned (stale-row delete =true; foreign/row-less =false)- Same-owner re-acquire disposition pinned (and flagged if it differs from the SQLite arm's)
- Silent lapse posture documented (no revocation event; no general expiry sweeper)
cargo test -p alkstore-postgres(harness server), clippy-D warnings, fmt clean; gates green server-less
References
- docs/architecture/core-contract.md (named locks section)
- docs/architecture/decisions/008-contract-v1-pinning.md §7 (guarantee row)
- docs/architecture/decisions/023-fourth-review-round.md §2 (duration kind)
- docs/architecture/engine-postgres.md (Mapping the contract: named locks)
- docs/research/poc-pg-posture-findings.md (the lock probe row)
- alkstore-sqlite/src/lock.rs (the structural twin — match its pinned dispositions)
- alkstore/src/lock.rs (the trait)
Notes
To be filled by implementation agent
Summary
To be filled on completion