Merge pull request 'Issue 264: a self-updating engine lost the report of the apply that delivered it' (#120) from issues/264-self-update-lost-report into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
This commit was merged in pull request #120.
This commit is contained in:
+72
@@ -0,0 +1,72 @@
|
|||||||
|
---
|
||||||
|
status: located
|
||||||
|
opened: 2026-10-06
|
||||||
|
located-in: [mesh-host]
|
||||||
|
fixed-by:
|
||||||
|
amended-design:
|
||||||
|
---
|
||||||
|
|
||||||
|
# 264. A self-updating engine lost the report of the apply that delivered it
|
||||||
|
|
||||||
|
## Symptom
|
||||||
|
|
||||||
|
One declaration for the anchor carried both a new controller and a new version of the host. The
|
||||||
|
host applied it and said, in its journal:
|
||||||
|
|
||||||
|
- `host <version> is delivered; standing aside so the launcher runs it`
|
||||||
|
- `applied, and could not tell the mesh: reporting: context canceled`
|
||||||
|
|
||||||
|
The new host started and said `in the mesh, hearing what this node should be`, and nothing more
|
||||||
|
about that declaration. The controller's release plan waits for the first machine to report the
|
||||||
|
exact digest of the declaration it was sent. That report never came, so the plan waited until a
|
||||||
|
person pushed again by hand.
|
||||||
|
|
||||||
|
This is the same family as [issue 257](../257-a-plan-waited-on-a-declaration-its-first-machine-never-reported/00-report.md)
|
||||||
|
and [issue 261](../261-a-module-was-applied-and-given-back-half-a-minute-later/00-report.md): the
|
||||||
|
machine did what it was sent, and the report the plan waits on did not say so.
|
||||||
|
|
||||||
|
## Cause
|
||||||
|
|
||||||
|
Standing aside for a successor ([ADR 0141](../../02-DECISIONS/0141-the-host-delivers-its-own-successor.md)) is
|
||||||
|
decided inside the apply, once the apply has finished, and it cancels the link's context. The link
|
||||||
|
then published the apply's report on that same cancelled context, and the bus refused it before it
|
||||||
|
left. The declaration was then acknowledged anyway, so the mesh did not deliver it again, and the
|
||||||
|
new host had nothing that told it a report was owed.
|
||||||
|
|
||||||
|
A crash or power cut between the apply and the report has the same shape. The declaration is
|
||||||
|
delivered again in that case only because it was not yet acknowledged, and nothing on the machine
|
||||||
|
records that a report is owed.
|
||||||
|
|
||||||
|
## Fix
|
||||||
|
|
||||||
|
Two parts, in the host:
|
||||||
|
|
||||||
|
1. The report of an apply, and of a declaration set aside for a newer one, is published on a context
|
||||||
|
that standing aside does not cancel. It is still limited by the host's timeout, and it is sent
|
||||||
|
before the connection is closed. After an apply that stood aside, nothing further is applied.
|
||||||
|
2. The report of the last apply of a declaration from the mesh is kept beside the node's state until
|
||||||
|
the broker has taken it. When a host links, it first sends any report still kept, before it applies
|
||||||
|
anything newly delivered, so the re-sent report cannot arrive after a newer one. What is re-sent
|
||||||
|
is exactly the report the apply made, with the same digest and the same outcome. It is never a new
|
||||||
|
description of the machine, so it cannot claim that something was applied when it was not. A
|
||||||
|
report that names no declaration, such as a refused one, clears what was kept. A node that never
|
||||||
|
applied anything sends nothing.
|
||||||
|
|
||||||
|
## How it is checked
|
||||||
|
|
||||||
|
These tests in the host fail without the fix:
|
||||||
|
|
||||||
|
- `TestAnApplyThatEndsTheLinkIsStillReported`: an apply that cancels the link still has its report
|
||||||
|
delivered, and its declaration is settled after the report.
|
||||||
|
- `TestAReportLostAfterTheApplyIsSaidOnTheNextLink`: a report the broker refused is sent again on the
|
||||||
|
next link, unchanged.
|
||||||
|
|
||||||
|
These tests guard the edges:
|
||||||
|
|
||||||
|
- `TestNothingIsSaidAgainWhenNothingWasLost`: nothing is re-sent when nothing was lost.
|
||||||
|
- `TestTheKeptReportSurvivesTheHost` and `TestNothingKeptWhenNothingWasApplied`: the kept report
|
||||||
|
survives a restart exactly as it was made, and it is cleared only by a report about the same
|
||||||
|
declaration.
|
||||||
|
|
||||||
|
Once the fix is rolled out, the live check is the next declaration that carries a new host version.
|
||||||
|
The first machine's report should reach the plan without anyone pushing by hand.
|
||||||
Reference in New Issue
Block a user