fix(backups): give the off-host verdicts slack for a Berlin night that is 25 hours long

The threshold was the schedule period with no budget on top of it. Two things
spend that budget on a host where nothing is wrong. The cron runs 02:30
Europe/Berlin, so on the DST fall-back Sunday the gap between two runs is 25
hours and every account on every host would cross one period on the same
morning. And the ledger instant is when that account's object landed, by
design, so on a cohort walked one account at a time an account reached an hour
later tonight than last night drifts past 24 with two clean runs behind it.

The schedule period and the verdict threshold are now separate numbers. The
period is still what the card quotes; the threshold is the period plus six
hours, applied to both steps, so due still means one run produced nothing and
stale still means two. The fall-back night is pinned in the unit file by its
real dates rather than by an arithmetic 25, and a genuinely missed night at 31
hours still reads due. The runbook says why the slack is there.
This commit is contained in:
Marc-André Bombeck committed 2026-09-10 10:09:59 +02:00
1 parent e64435f6a5
commit cfc19a211c
5 files changed
+97 -17

No files matched your search

+8
View File
@@ -228,6 +228,14 @@ how that compares with the nightly schedule. **Fresh** is inside one run,
did not, and **never** means no object has ever landed. On a host without
`BACKUP_S3_*` the card says off-host backup is not configured and stops there.
Each verdict carries six hours of slack on top of the schedule's own 24, and
that slack is load-bearing on two nights. The cron runs at 02:30 Europe/Berlin,
so on the DST fall-back Sunday two consecutive runs are 25 hours apart; and the
timestamp is when _that account's_ object landed, so on a cohort walked one
account at a time an account reached later tonight than last night drifts by
hours. Without the slack a healthy host would paint its whole cohort **due**
once a year.
The verdicts come from a ledger the worker writes when the object lands
(`offhost_backup_state`), not from a listing of the bucket. Keep the worker's
grant as documented — PutObject, GetObject, AbortMultipartUpload — and the card