Skip to content

serve: cancel timed-out queries and expose workspace state in /metrics - #524

Merged
tinder-maxwellelliott merged 1 commit into
Tinder:masterfrom
maxwellE:claude/exciting-mccarthy-hvrs29
Oct 16, 2026
Merged

tinder-maxwellelliott merged 1 commit into
Tinder:masterfrom
maxwellE:claude/exciting-mccarthy-hvrs29

Conversation

@tinder-maxwellelliott

Copy link
Copy Markdown
Collaborator

Fixes #518.

A query that outlived --requestTimeout kept running after the 504: it held the workspace, checked out revisions, ran bazel query, and then wrote hashes to the local and shared cache, with no way for the client to tell when the checkout was free again. A client that touched the checkout early could get a hash of a changed tree cached under its SHA and served fleet-wide.

Both approaches the issue proposes are implemented:

  • /metrics reports activeQueries (queries accepted and not yet finished, including abandoned ones) and workspaceBusy (whether any operation holds --workspacePath), so a client can wait for the workspace before reusing it.
  • A timed-out query is cancelled rather than abandoned. A new cancel::Cancellation token runs every git and Bazel subprocess the query spawns and kills them on cancel, the generation it did not finish is never written to any cache tier, and the 504 is sent only after the query has released the workspace. The response body carries cancelled and workspaceBusy.

State.workspace_lock becomes a Workspace that records its holder's token: git_output and the server's BazelOptions pick the token up from it, and a query cancelled while still queued gives up instead of taking the workspace for nothing.

Fixes Tinder#518.

A query that outlived `--requestTimeout` kept running after the 504: it
held the workspace, checked out revisions, ran `bazel query`, and then
wrote hashes to the local and shared cache, with no way for the client
to tell when the checkout was free again. A client that touched the
checkout early could get a hash of a changed tree cached under its SHA
and served fleet-wide.

Both approaches the issue proposes are implemented:

* `/metrics` reports `activeQueries` (queries accepted and not yet
  finished, including abandoned ones) and `workspaceBusy` (whether any
  operation holds `--workspacePath`), so a client can wait for the
  workspace before reusing it.
* A timed-out query is cancelled rather than abandoned. A new
  `cancel::Cancellation` token runs every git and Bazel subprocess the
  query spawns and kills them on cancel, the generation it did not finish
  is never written to any cache tier, and the 504 is sent only after the
  query has released the workspace. The response body carries
  `cancelled` and `workspaceBusy`.

`State.workspace_lock` becomes a `Workspace` that records its holder's
token: `git_output` and the server's `BazelOptions` pick the token up
from it, and a query cancelled while still queued gives up instead of
taking the workspace for nothing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhN3zsapeda1JRboWAeS8w
@tinder-maxwellelliott
tinder-maxwellelliott merged commit 362b907 into Tinder:master Oct 16, 2026
21 checks passed
maxwellE added a commit to maxwellE/bazel-diff that referenced this pull request Oct 16, 2026
Resolves the src/server.rs conflicts with Tinder#524, which replaced the
State literal with State::new. The in-memory tier is now constructed
there, and the remote-cache tests keep their compressed and plain
fallback responses on top of the shared ready_state helper.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gs1vjHt61po6uHgkYuh68N
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.

serve: let a client know when an abandoned query has released the workspace

2 participants