5.9 KiB
REPORT — v0.168.0: Customer-configurable backup window ("Mentési időablak")
Date: 2026-07-24 · Deployed & verified live on guest 9201; box left configured at 02:30.
1. Baseline
| Repo | main @ start |
version | → |
|---|---|---|---|
| felhom-controller | e33c1ae |
v0.167.1 | v0.168.0 (committed 82c67e3) |
Verified against live Gitea at task start (HEAD == origin == live). No agent coupling; MinAgent unchanged.
2. What shipped
ONE customer setting — "Mentési időablak kezdete" (window start W) — drives every nightly leg at
FIXED, never-stored offsets so misordering is impossible: DB dump at W, tier-2 at W+60m, off-box
at W+105m (wrap-safe). The whole-guest (agent PBS/vzdump) cycle is gated to [W+2h, W+6h) with a
safety valve. Precedence: settings > controller.yaml db_dump_schedule > "02:30". Changes apply
without restart.
3. Files
- New
internal/backupwindow/(backupwindow.go + _test.go) — pure time math:ParseHHMM/FmtHHMM/LegTimes/GateWindow/EffectiveWindow/Valid; offsets are constants (derived, never stored). internal/scheduler/scheduler.go(+ new _test.go) —UpdateDaily(name,timeStr) bool, per-daily-job bufferedreschedchan, acase <-job.reschedinrunDailyJob, Schedule read under the mutex.internal/settings/settings.go—BackupWindowStartfield + Get/Set.internal/quiesce/quiesce.go(+ new quiesce_window_test.go; fakes updated in quiesce_test.go / quiesce_8b2_test.go) —Backend.Duenow returns the backup age;Options.WindowStartFn/Cadence;scheduledRunAllowedpredicate + Budapest helper; gate on the scheduled path inrunOnce.internal/web/backup_handlers.go(+ new backup_window_test.go),handlers.go,server.goroute,templates/backups.html— the "Mentési időablak" card + POST/backups/window.cmd/controller/main.go— the three Daily legs + backup-cache + initial-cache + quiesce loop wired from the effective window.- Docs:
CHANGELOG.md,CONTEXT.md,controller/README.md,REUSE.md(UpdateDaily + backupwindow + 3rd Budapest-loader duplication note), thisREPORT.md.
Note: a stray
gofmt -w internal/ cmd/reformatted ~46 unrelated (non-gofmt-clean) files; all were restored toorigin/mainso the commit is surgical — only the files above are in the diff.
4. Tests + red-proofs (all recorded)
go build ./... && go vet ./... && go test ./... — 27 packages pass, 0 fail. Template/design gates
(template_id / emoji / mojibake / native-confirm) all OK.
| Group | Test(s) | Red-proof (mutate → FAIL → restore) |
|---|---|---|
| A | LegTimes (02:30/23:30/22:00/00:00, wrap), LegTimes_InvalidRejected, GateWindow |
drop the FmtHHMM modulo → LegTimes("23:30") yields "24:30"/"25:15" → FAIL confirmed |
| B | EffectiveWindow precedence table (settings>yaml>"02:30", corrupt falls through) |
— |
| C | UpdateDaily_MutatesAndSignals, _UnknownAndInvalid, _GoroutineConsumesReschedule |
remove case <-job.resched → signal stays buffered → immediacy test FAIL confirmed |
| D | scheduledRunAllowed truth table (inside/boundary/outside/valve/wrap/nil-age) + Loop integration (defer outside / run inside / valve runs / manual TriggerNow never gated) |
invert the valve >→< → starving-box + no-valve cases FAIL confirmed |
| E | BackupWindowSave_Valid (settings + 3× UpdateDaily + flash), _Invalid (nothing stored + error flash) |
skip the Valid() check → invalid value gets stored → FAIL confirmed |
Existing quiesce/scheduler/web suites still pass unchanged.
5. Deploy + live validation (guest 9201)
Built felhom-controller:0.168.0 (145M) from the clean pushed tree; deployed via bootstrap →
Up (healthy), Controller elindult (0.168.0). Startup registered the legs at the default window:
db-dump 02:30 · tier2-backup 03:30 · offbox-backup 04:15 (CEST). Method: endpoint-level (in-guest
curl to 172.17.0.2:8080, Host: felhom.demo-felhom.eu; login 302 + scraped session CSRF).
Save a window (POST /backups/window, window_start=22:00) → 303:
- Page re-rendered: input
value="22:00", derived rows22:00 / 23:00 / 23:45, rendszermentéskb. 00:00–04:00 között(W+2h..W+6h, wrap-safe). - Logs (NO restart):
db-dump rescheduled 02:30 → 22:00,tier2-backup 03:30 → 23:00,offbox-backup 04:15 → 23:45,backup window set to 22:00 (legs 22:00/23:00/23:45).
Restore (window_start=02:30) → 303: page shows 02:30 / 03:30 / 04:15 + kb. 04:30–08:30 között;
logs show the three legs rescheduled back. Box left at 02:30.
6. NOT live-exercised on 9201 (stated method)
- The disk-tier window-gate DEBUG denial could not be triggered live: the demo host agent is DOWN
for the remote-site window (its
localapibinds192.168.0.162, which doesn't exist there), so the quiesce loop's/backup/duecall errors before the gate is reached. The gate + safety valve + the manual-never-gated property are fully covered by Group D (truth table + Loop integration). Re-verify the live DEBUG line once the agent is reachable again. - Browser visual check of the "Mentési időablak" card layout is Viktor's acceptance step (the rendered HTML strings are confirmed; the pixels are not).
7. Observations (out of scope — documented only)
- Saving explicitly writes
backup_window_start:"02:30"— functionally identical to the empty/default state, so the box is correctly "at 02:30" either way. - Cadence for the safety valve defaults to 24h controller-side (the agent's
/backup/dueresponse carries no cadence field); if cadence policy ever becomes hub/agent-driven, thread it through instead of the constant. - Three Budapest-timezone loaders now exist (scheduler, web, quiesce) — noted in REUSE.md §6; kept local to avoid a scheduler↔quiesce import edge.