v0.228.0 — the off-site check reads the data; the debug page stops lying (R-399 + R-400)
gates / gates (push) Successful in 12s
gates / gates (push) Successful in 12s
R-399: monitoring.integrity.read_data_subset defaults to 100%. A pack damaged without changing its size made plain `restic check` report "no errors were found" on demo-hp 2026-08-30; every read-data form caught it. Cost on that 134 MB store: 35.0s structure vs 39.2s at 100%. "off" (any case) is the off token; empty means not-configured, therefore the default; a malformed value falls back to the DEFAULT, never to structure. A completed check over 5 minutes logs a WARN naming the duration, the depth and R-401 — operator log only, no hub event, no depth change. The depth is now recorded with the verdict (LastIntegrityDepth; empty = NOT RECORDED, never "structure"). R-400: 24 debug-page references, 17 dispatched, 7 dead — three of which fetched on page LOAD, so those panels were permanently blank. backup/crossdrive implemented; backup/infra, hub/infra-push, dr/infra-status, storage/watchdog-status and both storage/simulate-* deleted with their panels and JavaScript. scripts/debug_route_gate.py fails in both directions and is registered after the seven were resolved. 18 referenced, 18 dispatched, none orphaned. Corrections: the dead-field warning in report/types.go said the controller runs no integrity check and the notifiers are called from nowhere — both false since v0.227.0. controller.yaml.example gains its missing integrity: block. integrityCheckTimeout's "ships OFF" comment rewritten.
This commit is contained in:
@@ -188,11 +188,27 @@ type PingUUIDsConfig struct {
|
||||
// is on. R-341 is the failure that shape avoids: a dated check that was quietly missed for five days
|
||||
// because nothing asked again.
|
||||
//
|
||||
// IntegrityReadDataSubset is EMPTY by default and that is a decision, not an oversight (R-399). An
|
||||
// empty value runs restic's structure-and-index check, which downloads no pack data. A value like
|
||||
// "5%" adds `--read-data-subset=5%`, which downloads and re-hashes that fraction of the store every
|
||||
// run — a bandwidth and money cost that nothing has yet measured against the real store, so the
|
||||
// default must not be chosen here.
|
||||
// IntegrityReadDataSubset chooses HOW DEEP the check looks, and since 2026-08-31 it DEFAULTS TO
|
||||
// FULL DEPTH — an absent or empty value re-reads 100% of the stored data (R-399, Viktor's ruling).
|
||||
//
|
||||
// This paragraph replaces one that argued the opposite. That argument was correct on the day it was
|
||||
// written, when nothing had measured the cost; it was overtaken by a measurement the next day.
|
||||
//
|
||||
// **The structure check does not detect a size-preserving pack corruption.** On demo-hp, 2026-08-30, a
|
||||
// pack was damaged WITHOUT changing its size: plain `restic check` reported `no errors were found` and
|
||||
// exited clean, and every read-data form caught it. A structurally-verified store is one whose rot is
|
||||
// found at restore time, with a customer waiting. That sentence is the reason for the default and it
|
||||
// is what should stop anyone turning it back down to save four seconds.
|
||||
//
|
||||
// The cost, same store and day (140 829 678 B / 2 651 blobs / 67 snapshots): structure 35.0 s,
|
||||
// 10% 35.9 s, 50% 37.3 s, 100% 39.2 s.
|
||||
//
|
||||
// Accepted values: absent or empty -> the default (100%); "off" (any case) -> structure and index
|
||||
// only; any form restic accepts for --read-data-subset ("10%", "1/7", "50M") -> itself. Anything else
|
||||
// WARNs and falls back to the default, never to structure — a typo must not quietly remove the
|
||||
// protection. The default constant, the off token and that reasoning live in
|
||||
// internal/backup/offbox_integrity.go, beside defaultIntegrityMaxAgeDays and NOT in applyDefaults:
|
||||
// both integrity defaults are resolved in one accessor each, next to the argument that justifies them.
|
||||
type IntegrityConfig struct {
|
||||
MaxAgeDays int `yaml:"max_age_days"`
|
||||
ReadDataSubset string `yaml:"read_data_subset"`
|
||||
|
||||
Reference in New Issue
Block a user