Skip to content

Bound lock waits for human kind-word review decisions - #828

Merged
WaylandYang merged 1 commit into
deeplethe:devfrom
Maya-Kid:codex/bound-human-review-locks
Sep 20, 2026
Merged

WaylandYang merged 1 commit into
deeplethe:devfrom
Maya-Kid:codex/bound-human-review-locks

Conversation

@Maya-Kid

Copy link
Copy Markdown
Contributor

A review click currently waits indefinitely behind a locked kind-word binding or entity projection. Reproduced through the authenticated route on dev at c6029069146b53294ea8f457d09d5f49684f709e: it remained pending for over six seconds after observing the PostgreSQL lock wait, then returned 200 only after the blocker released its entity lock.

The human entry point now sets a transaction-local two-second lock_timeout, writes the binding and projection through the same shared implementation, and finishes rollback before returning 409 on 55P03. The review page shows a retry message in English or Chinese. Background alignment keeps its existing wait policy. Two seconds is an interactive lock-wait budget, not a total request or query execution deadline.

Validation on Linux, Rust 1.98.1, isolated PostgreSQL 16.15 / pgvector 0.8.6, with database tests required:

  • Authenticated HTTP regressions for binding, apply and unapply contention; complete binding/entity snapshots, no success jobs/audit/events on timeout, unlock-and-retry, and preservation of manual entity types.
  • Single-connection pool checks preserve both backend PID and the prior 7s session setting after failure and success. Agent waiting, human precedence, non-lock database errors, invalid input, authentication, viewer permissions and cross-base rejection are covered.
  • Removing the local timeout makes the projection regression fail at its response deadline; restoring it passes all five new regressions. All four existing type-alignment regressions also pass.
  • Workspace fmt, clippy (--locked --workspace --all-targets -- -D warnings), build and tests pass: 956 passed, 0 failed, 1 existing live-HTTPS test ignored. Linux frozen-lockfile frontend install, 91 tests, style guard, typecheck and production build pass.

No migration. Reverting restores the prior wait policy. The existing post-commit enqueue boundary and phrase recomputation in #800 are unchanged; this does not claim to bound every synchronous handler.

Refs #798

Signed-off-by: dada-yan <BinjunYann@gmail.com>
@WaylandYang

Copy link
Copy Markdown
Contributor

Reviewed and merging. The parts that carry the risk are right:

  • SET LOCAL lock_timeout keeps the change transaction-scoped, so a pooled connection is not handed back altered — and the test that checks the prior 7s session setting survives is the right test to have written.
  • The rollback completes before the response, and both errors are preserved if the cleanup itself fails.
  • 55P03 is the code lock_timeout raises, not a near miss.
  • The human path and the background path share write_decision_and_projection, so they cannot drift apart later.
  • Review.tsx keying off e.status === 409 rather than matching the message text is the right call.

One note for later, not blocking this. error.rs states that every error a user can hit should carry a stable code, because the backend no longer owns the locale (0004) and the interface looks the wording up by code. AppError::Conflict(String) has no code, and this is an error users are meant to hit, so the client can only infer it from a bare 409 — a second 409 on that route would render the same "busy, try again" wording. There is no coded 409 variant today, so this is a gap in the error type rather than something to correct here.

@WaylandYang
WaylandYang merged commit bce6fbd into deeplethe:dev Sep 20, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants