Features: #315 — fixed placement honours the unreachable set

Dai Ha
2026-09-04 14:02:34 +07:00
parent 9d62717837
commit 7b99569d5e
+25
@@ -3835,3 +3835,28 @@ ordinary "a branch named X already exists" refusal would delete the operator's e
directory on that refusal, so no directory means nothing was created and the branch is not ours to
touch. Removing that check makes `addFailureBeforeCreatingAWorktreeIsQuiet` fail with the branch
actually deleted. Do not remove it.
## `fixed` placement honours the failover loop's unreachable set
**What.** The `fixed` placement policy now skips a profile that the current spawn attempt has
already found unreachable. It checks `ctx.unreachable()` in both places it picks a profile: the
configured default, and the fallback walk over the remaining candidates.
**On.** Only when `placement: fixed` is set in `fleetd.yaml`. The live fleet runs `weighted`, which
already honoured the set, so this changed nothing here — it was reachable only for an operator who
had switched to `fixed`.
**Why it exists.** `CompositePeerLauncher` retries a failed spawn by adding the dead profile to the
unreachable set and asking the policy again, and its own comment says why: *"Update the context for
the next selection so the policy excludes this profile."* `fixed` ignored the set, so it handed back
the same dead profile on every attempt. The loop then spent all of its attempts on one profile and
reported failure, while healthy profiles sat idle and were never tried. The failover existed but
could not move.
**One thing to know for maintenance.** `fixed` ignoring the *load caps* is deliberate and stays —
that is what "fixed" means. Reachability is not a cap, and the javadoc now separates the two so the
next reader does not undo this as a bug fix. Also note what does **not** work: breaking out of the
retry loop early when the policy returns an already-unreachable profile only makes it fail faster on
the same dead profile, because only the policy chooses what comes next. The failure message now
counts *distinct* candidates, so "tried 1 distinct candidate(s)" is the visible symptom of this
whole class of problem.