From 2e2be955e9a8002a2d0ea6aa61f318ac0286b568 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Oct 2026 01:54:42 +0200 Subject: [PATCH] ADR 0269: say that a unit stopped by hand while held cannot be told apart, that a restored Persistent timer catches up at once, and what is left alone Third review: a person's stopping a unit the mesh also held stopped leaves no trace, so it is started again on removal; the home server's restored weekly timer would start a scrub of about 46 hours at once. A masked or since-changed unit is left alone, and a failed restore waits. --- ...n-stopped-is-started-again-when-it-goes.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/02-DECISIONS/0269-what-the-meshs-own-declaration-stopped-is-started-again-when-it-goes.md b/02-DECISIONS/0269-what-the-meshs-own-declaration-stopped-is-started-again-when-it-goes.md index 9b79485d..4101019d 100644 --- a/02-DECISIONS/0269-what-the-meshs-own-declaration-stopped-is-started-again-when-it-goes.md +++ b/02-DECISIONS/0269-what-the-meshs-own-declaration-stopped-is-started-again-when-it-goes.md @@ -51,6 +51,12 @@ enabled or disabled where the declaration says. When the service's declaration g found running and declared stopped is started again, and one found enabled and declared disabled is enabled again. The report says so as `restored`, and the plan says it before the apply does.** +**Only a unit exactly as the mesh held it.** At removal the unit must still be the stopped and disabled +the declaration held it to. A masked unit is somebody's word that it must not run, and is left as it is. +So is a unit somebody started or enabled since. In both cases the report says why. A restore that fails +(the start refused, or the unit not running after it) puts back what that attempt changed. It is reported +as *waiting*, never as an error that makes an apply fatal, and the next apply tries again. + 0118's other rules stand: - a unit found running and never stopped by the mesh is left running; @@ -68,6 +74,16 @@ before the mesh came, and the mesh's stopping it was the mesh's doing, which goe - Unassigning the `zfs` module gives the home server back its distribution scrub timer, running and enabled. A module may take over a machine's unit by holding it stopped, and its removal undoes that. - A unit that is moved to another unit name (ADR 0118's "moved") is given back by the same rule. +- **A unit a person stopped by hand while the mesh held it cannot be told apart, and is started again.** + While the declaration holds a unit stopped and disabled, a person who also stops or disables it by hand + leaves no trace: the unit is in the state the mesh holds it to either way. At removal it is started and + enabled again, as it was found before the mesh. A person who wants it to stay off after the module goes + must disable it again afterwards, or mask it, which removal respects. +- **A restored timer catches up at once.** A timer with `Persistent=true` that was stopped past its + scheduled time fires as soon as it is started again. On the home server the distribution's weekly scrub + timer is such a timer, and a scrub of its pool took about 46 hours (2026-10-05 00:08 to 2026-10-06 + 22:06). Unassigning the `zfs` module therefore starts a scrub of about 46 hours, within the hour of + the timer's random delay. Unassign it when that load is acceptable. - **Harder:** a unit the mesh stopped and that should *stay* stopped after the module goes (one that was found running by accident) is now started again. Saying so needs a field on the resource, which no module needs yet. Until one does, the plan's `restore … started … again` step is where it is seen. @@ -79,6 +95,9 @@ before the mesh came, and the mesh's stopping it was the mesh's doing, which goe | A unit found running and enabled, declared stopped and disabled, is started and enabled again when undeclared, and the report says `restored` | mesh-host `internal/apply/giveback_test.go`, `TestAUnitTheMeshStoppedAndDisabledIsGivenBackRunningAndEnabled` | | A unit found stopped stays stopped; one never stopped by the mesh is left as it is | `TestOnlyWhatTheMeshsDeclarationStoppedIsStartedAgain` | | A record without what was declared starts nothing | `TestARecordWithoutWhatWasDeclaredStartsNothing` | +| A masked unit, or one started or enabled since, is left as it is, and the report says why | `TestAMaskedOrChangedUnitIsLeftAloneOnRemoval` | +| A failed restore waits and is never fatal, and the record stays for the next apply | `TestAFailedRestoreWaitsAndIsNeverFatal` | +| Every systemctl call that names a unit passes `--` before it | mesh-host `internal/system/dashdash_test.go` | | The plan says it before the apply does | `TestThePlanSaysAStoppedUnitIsStartedAgain` | | 0118's existing rules | mesh-host `internal/apply/found_test.go`, unchanged and passing |