Issue 325: assign said no module of that name while the module's build ran
Register the symptom and the fix in mesh-controller#150 (replay R325 in mesh-lab#68), and name the pending assignment in the glossary.
This commit is contained in:
@@ -176,6 +176,9 @@ and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 02
|
||||
**Uses:** node, machine, module, seat, setting (Module), manifest (Module).
|
||||
|
||||
- **assignment** — a module put on a node, with the settings that node gives it.
|
||||
- **pending assignment** — an assignment of a module whose build is still running, kept and made when that
|
||||
build registers the module, or ended with why when it does not
|
||||
([issue 325](../04-ISSUES/325-assign-said-no-such-module-while-its-build-ran/00-report.md)).
|
||||
- **scope** — where a seat or a claim holds: `node`, `site` or `mesh`. `node` is also the scope's
|
||||
value in a manifest.
|
||||
- **capacity** — how many holders a seat takes. A capacity-1 seat is exclusive. A higher-capacity seat
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
---
|
||||
status: located
|
||||
opened: 2026-10-08
|
||||
located-in: [mesh-controller cmd/mesh-controller (acts.go, the assign act; upgrades.go, the merge's build request), mesh-controller internal/inventory (the build request and pending assignment records)]
|
||||
fixed-by: mesh-controller#150, mesh-lab#68
|
||||
replay: R325
|
||||
amended-design:
|
||||
---
|
||||
|
||||
# 325. Assign said "no module of that name" while the module's build ran
|
||||
|
||||
## What was observed
|
||||
|
||||
On 2026-10-08 the catalogue's pull request adding a new module, `sensors`, merged. Since issue 300's fix, a
|
||||
merge that adds a module asks the build seat for it, and the build registers the module when its outcome is
|
||||
taken in. About a minute after the merge, `mesh-controller.assign {node: "g14", module: "sensors"}`
|
||||
answered:
|
||||
|
||||
> no module of that name: sensors
|
||||
|
||||
A few minutes later the same call worked. The build had not finished the first time.
|
||||
|
||||
The operator read the answer as "you forgot to register the module" and asked whether `assign` could offer
|
||||
to register it when it is not found.
|
||||
|
||||
## Why it is an issue
|
||||
|
||||
The answer was true and misleading. The controller had itself asked for the build a minute earlier, and it
|
||||
answered as if it had never heard of the module. It kept no record of a build it had asked for until the
|
||||
outcome came back, so `assign` could not tell three different situations apart:
|
||||
|
||||
1. a build is in flight, and the module will exist in minutes;
|
||||
2. the module's directory is known (a merge or a person asked for its build) and it was never registered,
|
||||
because the build failed, was not registered, never answered, or could not be asked;
|
||||
3. the name is unknown: a typo, or a module in no repository the mesh builds from.
|
||||
|
||||
Each needs a different act from the person, and the one answer given fitted only the third. Issue 300
|
||||
removed the second act by hand from adding a module; this answer put it back, as a wait and a retry that
|
||||
nothing told the person to make.
|
||||
|
||||
## Fix
|
||||
|
||||
**The controller keeps every build request it makes, and `assign` reads them** (mesh-controller#150). A build request is kept when a merge asks for a new module, when a person runs `build`, and when
|
||||
a plan asks for a tier. It is kept with its repository, directory, branch and the merge's commit. A merge
|
||||
whose request could not be made is kept too, with the reason. Requests older than 30 days are deleted.
|
||||
The outcome is the `build` record with the same id.
|
||||
|
||||
An assignment of a module the catalogue does not hold now says which case it is in:
|
||||
|
||||
- **A build is in flight**: "sensors is not registered yet: it is being built from
|
||||
novox/mesh-catalog@3da80a4b (modules/sensors) since 15:38:17, as build build-…; it can be assigned once
|
||||
that build registers it". The assignment is kept as a **pending assignment** (new glossary word). When
|
||||
the build registers the module, the assignment is made, by the same act and with the same checks as by
|
||||
hand. If the build fails, is not registered, or says nothing within two hours, the pending assignment
|
||||
expires with the build's own words. `status` lists every pending assignment that is waiting, and every one
|
||||
that ended in the last day; while one waits, or one expired or was refused, status does not call the mesh
|
||||
well. `unassign` withdraws a pending assignment.
|
||||
- **Known, not built**: said with what came of the last request (failed, with the builder's first line;
|
||||
no outcome; could not be asked), and refused. The answer offers `build`, and `assign` with the new
|
||||
argument `build: "true"`. That argument asks for the build from where the last request was made and keeps
|
||||
the assignment pending on it.
|
||||
- **Unknown**: refused as "no module of that name", as before. The answer adds the closest names the mesh
|
||||
holds and says how a module in a repository is built.
|
||||
|
||||
**Pending by default, with no argument to ask for it.** An assignment is what a person meant, and the
|
||||
controller already keeps it when its machine does not resolve. Nothing is sent until a push, or a walk if
|
||||
the module's first upgrade announcement finds it assigned. `unassign` undoes it. Asking for a
|
||||
second act once the build lands would bring back the two acts by hand that issue 300 removed. A build is
|
||||
never asked for by default: it runs on another machine, and a directory whose last build failed is a fault
|
||||
to look at before it is something to retry.
|
||||
|
||||
Several modules in one act are judged together (ADR 0207). So an act naming a module that is not registered
|
||||
is refused whole, with each module's case said, and nothing is kept pending.
|
||||
|
||||
**Not covered.** The controller cannot read the forge, so a module directory on a trunk that no merge
|
||||
announced since this fix, and no person asked to build, still reads as unknown. The refusal says how to
|
||||
build it.
|
||||
|
||||
## How it is checked
|
||||
|
||||
- `TestReplay325` replays the live case: a merge adds `modules/sensors`, `assign laptop sensors` runs
|
||||
before the build's outcome, and then the outcome registers it. The assignment must say the build and be
|
||||
made when the build lands. On the commit before the fix it fails with "no module of that name: sensors".
|
||||
It is R325 in mesh-lab's replays register (mesh-lab#68).
|
||||
- `cmd/mesh-controller/pending_test.go` has one test per case: a build in flight (the answer, the pending
|
||||
record, status and its JSON, the build applying it), a failed build expiring it and then reading as known
|
||||
and not built, `build: "true"` asking from the last request's source, an unknown name with the closest
|
||||
names, a several-module act refused whole, `unassign` withdrawing, and a build that says nothing expiring
|
||||
at the next look while a module registered meanwhile is assigned. The seat passes `build` and `unassign`
|
||||
refuses it.
|
||||
|
||||
No design names what `assign` answers for a module it does not hold, so no design is amended.
|
||||
Reference in New Issue
Block a user