Repository navigation
feat(547): in-flight slot expiry, backend.daemon.reclaim and typed admission reasons (slices 5–6) - #652
Merged
Conversation
Slice 5: an admitted slot's decoded request now carries an explicit
deadline (Phase::InFlight { started, deadline } driven by the new
request_deadline_ms limit). Past it the daemon frees the slot, closes the
worker's socket and records RetainedFailure { cause: Expired,
reply_sent: false }, so the caller observes an unknown outcome instead of a
silent hang.
backend.daemon.reclaim { slot, generation } is the authenticated,
generation-checked, one-shot operator verb: it closes the named worker's
socket, records Reclaimed, answers Invalid on a generation mismatch, never
restarts the daemon and never touches Workspaces. It joins the recovery
allow-list. Reclaimed and expired workers are detached (never joined), and
slot fences are keyed by generation so a stale worker's late clear_fence
cannot clobber a newer worker's fence.
Slice 6: the client no longer classifies a refused open by matching the
refusal message text. A failed open is typed from the channel error: a
notice is Capacity/Unavailable with resource, pool_vacant,
reserved_vacant, retryable and a retry_after hint; a legacy EOF answers
Unknown { observed }, never a guess at "no vacant slot"; a request whose
reply never arrives (reclaimed or expired worker) answers Unavailable
{ outcome: unknown }.
AdmissionReason is #[non_exhaustive] with constructor functions, the
capacity model's parse/to_sdk/exhausted are #[must_use], and the doc
comment records the version-skew matrix (new daemon x old binding, old
daemon x new binding, new control x old worker bundle).
mengmengmengqiang
changed the base branch from
fix/547-slice-34
to
layerfs_v2_0_0
November 12, 2026 03:20
This was referenced Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Slices 5–6 of #547, stacked on
fix/547-slice-34. An admitted slot's request now has a deadline, the operator gets a one-shotbackend.daemon.reclaimverb, and a refused open is typed from the channel error instead of from the refusal message text.19 files, +731 −175, two commits on top of the slice 3–4 branch.
What this does
Slice 5 — in-flight expiry and reclaim —
d1fc7e228Phase::InFlight { started, deadline }, driven by the newrequest_deadline_mslimit). Past it the daemon frees the slot, closes the worker's socket and recordsRetainedFailure { cause: Expired, reply_sent: false }, so the caller observes an unknown outcome instead of a silent hang.backend.daemon.reclaim { slot, generation }is the authenticated, generation-checked, one-shot operator verb: it closes the named worker's socket, recordsReclaimed, answersInvalidon a generation mismatch, never restarts the daemon and never touches Workspaces. It joins the recovery allow-list.clear_fencecannot clobber a newer worker's fence.Slice 6 — typed refusal outcome —
7a24b34c2Capacity/Unavailablewithresource,pool_vacant,reserved_vacant,retryableand aretry_afterhint; a legacy EOF answersUnknown { observed }and never guesses "no vacant slot"; a reply that never arrives (reclaimed or expired worker) answersUnavailable { outcome: unknown }.AdmissionReasonis#[non_exhaustive]with constructor functions; the capacity model'sparse/to_sdk/exhaustedare#[must_use].Test evidence
Dell
aluminium(x86_64, 88 cores),rustc 1.85.1:The 11 failures are not from this branch. I built and ran the same
-p layerfs-api -p layerfs-control -p layerfs-sandboxsuite on unmodifiede9b903eac: base fails 12 of those tests, and this branch's failing set is a strict subset of base's — zero new failures.They are a host limitation of the test machine, not of the code: the kernel-mount suites need
/dev/fuseowned by the test user and fail as a normal user withkernel attach Mount: Operation not permitted (os error 1)/FUSE device ownership/type. Run as root they pass, but the daemon refuses to start when the command uid equals the owner uid, sodaemon_slots/slot_stateneed a non-root user. The suite therefore cannot be green in one configuration on that host.Refs #547, #540 — not closing either.