Skip to content

engine: carry one queue hold with a reason rather than three parallel hold cells #1665

Description

@FSM1

Part of #992

comp:engine · M · crates/engine/src/sync/drain.rs, crates/engine/src/facade.rs, crates/wasm/src/lib.rs

Found by the simplify, reuse and altitude gates on PR #1658.

Problem

The drain holds the queue head for three reasons, and each has its own cell: BlockedOp for the quota, SettingsHold for a placement refusal, and BinIndexHold for a bin index the pass cannot read. All three carry the same three fields — op_id, node, one reason payload — and all three are mutually exclusive. Nothing makes the exclusion structural. Each halt arm clears the other cells by hand, and the invariant lives only in a comment:

One pass raises one halt, and each hold's own gate is what lets go of it — so taking one drops the others rather than leaving two cells claiming the same head for different reasons.

PR #1658 added the third cell and six such clear calls. A fourth reason makes it twelve, and a missed clear leaves two cells that name one head.

Scope

Replace the three cells with one QueueHold { op_id, node, reason }, where the reason is Quota { needed_bytes }, Settings(SettingsRefusal) or BinIndex(DefaultsReason). One pre-pass gate dispatches on the reason, so the per-arm clears go away and exclusion holds by construction.

The change is mechanical but wide: about 74 references across drain.rs, facade.rs, crates/wasm/src/lib.rs, crates/engine/tests/write_plane.rs, crates/wasm/tests/boundary.rs and the desktop tests. It replaces three public SnapshotView and SessionStatus fields and three wasm-bound classes, so it touches the TypeScript-facing surface.

AC

  • The drain holds one cell, and taking a hold cannot leave a stale one behind.
  • No halt arm clears another arm's state by hand.
  • The host reads the same information it reads today, through one field.

Body check 2026-09-15

Re-read on main at 588d646, after #1842 changed drain.rs:

  • The three cells are still there and no QueueHold type exists. The scope stands.
  • drain.rs makes 14 calls to clear_block, clear_settings_hold and clear_bin_index_hold. Four of those sit inside the three halt arms of apply_valve, which is the hand-clearing this issue removes.
  • The three names appear about 155 times in 18 files. Six are Rust: crates/engine/src/sync/drain.rs, crates/engine/src/sync/mod.rs, crates/engine/src/lib.rs, crates/engine/src/facade.rs, crates/wasm/src/lib.rs and crates/wasm/tests/boundary.rs, plus crates/engine/tests/write_plane.rs. The desktop surface is crates/fuse/tests/fuse_op_core.rs, which reads SessionStatus::blocked at two places.
  • The TypeScript surface is wider than the body states: packages/client protocol, codec and testkit, and five apps/web files, one of which is the QueueHoldNotice component.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    comp:enginecrates/engine — the stateful client brainv2-buildv2 rewrite build slice

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions