server: maintenance ticker drives forget/prune/check on cadence

Wires a 60s server-side ticker to the pure-logic maintenance.Decide
introduced in the previous commit. Decisions flow through a new
DispatchMaintenance method on *Server, which:

  - skips offline hosts (no pending_runs queueing — maintenance is
    not a backup, missed fires shouldn't pile up)
  - silently skips prune when admin creds aren't bound
  - pushes admin creds before prune, then dispatches with
    RequiresAdminCreds=true (same as operator-driven prune)
  - persists job rows with actor_kind="system"

Reshapes the forget wire payload from a single RetentionPolicy to a
ForgetGroups list (one tag + per-group keep-* per source group). The
agent walks the groups and runs `restic forget --tag <name> --keep-*`
once per group. Dead-code removed: CommandRunPayload.RetentionPolicy,
the old forget JSON-decode in cmd/agent, and the single-policy form of
restic.RunForget.
This commit is contained in:
2026-05-03 23:40:35 +01:00
parent ae96983877
commit 14b703be58
8 changed files with 559 additions and 62 deletions
+5 -2
View File
@@ -333,8 +333,11 @@ esac
tx := &fakeSender{}
r := New(Config{ResticBin: bin}, tx, 0)
keepLast := 1
policy := restic.ForgetPolicy{KeepLast: &keepLast}
if err := r.RunForget(context.Background(), "job-forget", policy); err != nil {
groups := []restic.ForgetGroup{{
Tag: "documents",
Policy: restic.ForgetPolicy{KeepLast: &keepLast},
}}
if err := r.RunForget(context.Background(), "job-forget", groups); err != nil {
t.Fatalf("RunForget: %v", err)
}
_ = firstEnvOfType(t, tx.envs, api.MsgJobStarted)