Hive Hive
Sign in

fix(specs): bound spec write lock waits so create can’t hang

GitHub issue · Closed

Metadata
Source
tuist/hive #102
Updated
Jul 5, 2026
Domains
Hive
Details

What

create_spec (via MCP and the dashboard) could hang indefinitely — validation passed, then the create wedged server-side and MCP clients timed out. This bounds every spec write so it fails fast instead of hanging.

Root cause

create_spec acquires the gapless-numbering advisory lock with the blocking pg_advisory_xact_lock (Hive.Specs.lock_specs_for_numbering/0), which has no timeout. The earlier lock hardening only landed as global connection parameters in config/runtime.exs — TCP keepalives + idle_in_transaction_session_timeout: 60s, but no lock_timeout.

idle_in_transaction_session_timeout only rolls back a holder that goes idle in transaction. A holder that is active — itself blocked waiting on another lock — is never cleared, so it wedges every subsequent create forever (matching the observed >1-day persistence: reads fine, create hangs). lock_timeout is the only bound that also covers pg_advisory_xact_lock acquisition.

The fix

  • Add Hive.Specs.write_transaction/1, which wraps create/update in a transaction that issues SET LOCAL lock_timeout = 10000 (bounds both the advisory lock and the optimistic-lock row UPDATE) and rescues Postgrex :lock_not_available (SQLSTATE 55P03) into {:error, :locked}.
  • Route create_spec/update_spec through it.
  • Surface {:error, :locked} in the MCP create_spec/update_spec tools ({"error":"locked","message":"…try again…"}) and the new/edit/show dashboard LiveViews (retry flash) instead of crashing.

Tests

  • Two new Mimic-based contract tests (create_spec_test, update_spec_test) prove the tools return locked rather than crash when a write is contended.
  • mix compile --warnings-as-errors, mix format, mix credo clean; 159 spec/LiveView/MCP-tool tests pass.

Reviewer notes

  • Deploying also clears any current wedge: the BEAM restart drops the stuck DB connection and releases its locks, so the existing jam clears on deploy and lock_timeout prevents recurrence.
  • The advisory-lock numbering is kept intentionally (gapless numbers — the sequence was dropped in migration 20260618000000); this only bounds the wait, it doesn’t change numbering semantics.
  • Out of scope / follow-up: Hive.Drops numbering (lock_drops_for_numbering/0) uses the same unbounded pg_advisory_xact_lock and has the identical latent bug. Left untouched here to keep the change tight; worth the same treatment.
Flights

Investigate, reproduce, or fix this item in an isolated repository. Each Flight preserves its outcome and agent session.

New Flights are paused Configure model inference, GitHub, and a sandbox provider to start another Flight. Existing results remain available below.
No Flights yet

Start a Flight and preserve its objective, outcome, and session here.

Comments
GA
github-actions[bot] Jul 2, 2026

Blick review didn’t run

The blick review step failed before producing a manifest, so there’s no review to post on this PR. This usually means the agent (opencode) couldn’t start — common causes are an expired or suspended model API key, a missing secret, or the workflow timing out.

See the workflow run for details: https://github.com/tuist/hive/actions/runs/28580810852

Commit: d926de83be934d4e2a865b3fd94cd4568f474d3f