The node-engine wakes the provisioner when an apply lets a file it refused be written (issue 924) #142

Merged
mesh-tools merged 2 commits from fix/provisioner-retries-on-declaration into main 2026-10-25 21:08:52 +00:00
Member

Issue 924 (the provisioner client's refused writes are never tried again), met live 2026-10-25 on ace: the client placed mesh-build-go's files one second before ace's declaration named them, the node-engine refused ('not a file this node's declaration names as filled'), nothing woke the client again, and mesh-build-go crash-looped on a missing broker file.

  • The filling engine (internal/filling) remembers what it refused or failed to write.
  • The agent calls Env.Settled(module) after a successful apply or removal, once what runs holds the module (afterApply runs before that, when the declaration does not name the new files yet).
  • On Settled, Engine.Knock touches the write socket the client watches when the declaration now names a refused path, now names the provisioner's account, or a write had failed; it says which in the journal. It takes the apply's lock (the one a Write takes), so a refusal still being judged when the apply settles is not missed, and it reads the declaration only when something is owed.

No timer: the knock is the node-engine's own event after an apply. The NATS-native trigger (the client reading its module's have) needs a controller grant and goes to ADR 0547's later milestones. The client side is mesh-catalog's PR of the same branch name; each works without the other (the client already watches the socket).

Checked: go test -race -count=1 ./... and go vet -tags integration ./... pass; the integration level was run locally once. No top-level test functions added (rows in TestAnUndeclaredPathIsRefused, including a deterministic race row, and the agent test checks Settled). No try (recovery mode: the operator merges by hand). This is the node-engine on every node.

Reviewed-by: review-prov@shanks at 338797a527

Issue 924 (the provisioner client's refused writes are never tried again), met live 2026-10-25 on ace: the client placed mesh-build-go's files one second before ace's declaration named them, the node-engine refused ('not a file this node's declaration names as filled'), nothing woke the client again, and mesh-build-go crash-looped on a missing broker file. - The filling engine (internal/filling) remembers what it refused or failed to write. - The agent calls `Env.Settled(module)` after a successful apply or removal, once what runs holds the module (afterApply runs before that, when the declaration does not name the new files yet). - On Settled, `Engine.Knock` touches the write socket the client watches when the declaration now names a refused path, now names the provisioner's account, or a write had failed; it says which in the journal. It takes the apply's lock (the one a Write takes), so a refusal still being judged when the apply settles is not missed, and it reads the declaration only when something is owed. No timer: the knock is the node-engine's own event after an apply. The NATS-native trigger (the client reading its module's have) needs a controller grant and goes to ADR 0547's later milestones. The client side is mesh-catalog's PR of the same branch name; each works without the other (the client already watches the socket). Checked: go test -race -count=1 ./... and go vet -tags integration ./... pass; the integration level was run locally once. No top-level test functions added (rows in TestAnUndeclaredPathIsRefused, including a deterministic race row, and the agent test checks Settled). No try (recovery mode: the operator merges by hand). This is the node-engine on every node. Reviewed-by: review-prov@shanks at 338797a52703177d1e4271d7c6e347f64d7f85d6
mesh-tools added 2 commits 2026-10-25 20:50:46 +00:00
ace's filling refused mesh-build-go's files as not named as filled 32 s before
its want arrived; after the apply that named them nothing asked again, and the
runtime crash-looped on its missing broker credential. The filling now keeps
what it refused or failed and, when the node agent says a module's apply or
removal settled (agent.Env.Settled, called once what runs holds it), touches its
write socket if the declaration now names such a path, names the provisioner's
account, or a write had failed; the client watches that socket and fills every
module again. Said in the journal each time.
Knock under the apply's lock, and read what is owed first (review of this fix)
mesh/delivery merged: source.main moved to novox/mesh-host@e196058f6fb0
mesh/delivery-group group fix/provisioner-retries-on-declaration merged: every member is merged
mesh/check pass 338797a52703 on d75c66dc7e27 | unit 2301 run, 3410 kept, 10 skipped | integration 2326 run, 3431 kept, 13 skipped | over bound: unit, …
338797a527
A write judged by the declaration before the apply settled could record its
refusal just after Knock found nothing owed: the original fault in a small
window. Knock now holds the apply's lock as a write does, reads no declaration
while nothing is owed, and its comment names Settled as its caller.
Author
Member

Delivery novox/mesh-host@338797a52703 — merged since 2026-10-25T21:08:54Z

Source — source.main moved to novox/mesh-host@e196058f6f. Whether it reached the machines is mesh-delivery-view's, derived from source.main, the wants and the haves.

Group fix/provisioner-retries-on-declaration: novox/mesh-catalog@d0566f9ade, novox/mesh-host@338797a527

  • composed together: pass — the checker's verdict at the members' heads (9eb0f92fd6b3)

Transitions

  • 2026-10-25 20:50 (new) → proposed (announced): novox/mesh-host#142's head announced
  • 2026-10-25 20:53 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail
  • 2026-10-25 21:08 ready → merged (merged): on the trunk its modules follow: merged there

The commit's note under refs/notes/mesh-plan keeps every transition of this change up to its merge: git log --notes=mesh-plan.

<!-- mesh-delivery:view --> **Delivery** `novox/mesh-host@338797a52703` — **merged** since 2026-10-25T21:08:54Z **Source** — source.main moved to novox/mesh-host@e196058f6fb0. Whether it reached the machines is `mesh-delivery-view`'s, derived from `source.main`, the wants and the haves. **Group** `fix/provisioner-retries-on-declaration`: novox/mesh-catalog@d0566f9ade9a, novox/mesh-host@338797a52703 - composed together: pass — the checker's verdict at the members' heads (9eb0f92fd6b3) **Transitions** - 2026-10-25 20:50 (new) → proposed (announced): novox/mesh-host#142's head announced - 2026-10-25 20:53 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail - 2026-10-25 21:08 ready → merged (merged): on the trunk its modules follow: merged there The commit's note under `refs/notes/mesh-plan` keeps every transition of this change up to its merge: `git log --notes=mesh-plan`.
mesh-tools merged commit e196058f6f into main 2026-10-25 21:08:52 +00:00
mesh-tools deleted branch fix/provisioner-retries-on-declaration 2026-10-25 21:08:53 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-host#142