fix: project finished backup jobs onto host row + smoke path tweaks

The dashboard's 'Last backup' column reads hosts.last_backup_at /
last_backup_status, but the WS handler only updated hosts.repo_status
on job.finished — backup terminations were silently dropped. Add a
SetHostLastBackup store method and call it from the same job.finished
switch that already handles init jobs.

Also: CLAUDE.md restage block uses /tmp/rm-smoke (the original
default) but the actual dev env runs out of $HOME/smoke. Update the
paths in the doc to match.
This commit is contained in:
2026-05-07 17:54:53 +01:00
parent b60c2c6f6b
commit 0a75b82c17
3 changed files with 32 additions and 13 deletions
+11 -5
View File
@@ -227,11 +227,17 @@ func dispatchAgentMessage(ctx context.Context, c *Conn, hostID string, env api.E
// a *success* — restic's idempotent init returns that when the
// repo is already initialised, which is the happy path for
// onboarding against an existing repo.
if job, err := deps.Store.GetJob(ctx, p.JobID); err == nil && job != nil &&
job.Kind == string(api.JobInit) {
status, errOut := repoStatusFromInit(string(p.Status), errMsg)
if err := deps.Store.SetHostRepoStatus(ctx, hostID, status, errOut); err != nil {
slog.Warn("ws: set host repo status", "host_id", hostID, "err", err)
if job, err := deps.Store.GetJob(ctx, p.JobID); err == nil && job != nil {
switch job.Kind {
case string(api.JobInit):
status, errOut := repoStatusFromInit(string(p.Status), errMsg)
if err := deps.Store.SetHostRepoStatus(ctx, hostID, status, errOut); err != nil {
slog.Warn("ws: set host repo status", "host_id", hostID, "err", err)
}
case string(api.JobBackup):
if err := deps.Store.SetHostLastBackup(ctx, hostID, string(p.Status), p.FinishedAt); err != nil {
slog.Warn("ws: set host last backup", "host_id", hostID, "err", err)
}
}
}
if deps.JobHub != nil {
+13
View File
@@ -81,6 +81,19 @@ func (s *Store) SetHostRepoStatus(ctx context.Context, hostID, status, errMsg st
return nil
}
// SetHostLastBackup projects a finished backup job onto the host row
// so the dashboard can show last-run state without trawling the jobs
// table. Called from the WS handler on job.finished where kind=backup.
func (s *Store) SetHostLastBackup(ctx context.Context, hostID, status string, when time.Time) error {
_, err := s.db.ExecContext(ctx,
`UPDATE hosts SET last_backup_at = ?, last_backup_status = ? WHERE id = ?`,
when.UTC().Format(time.RFC3339Nano), status, hostID)
if err != nil {
return fmt.Errorf("store: set host last backup: %w", err)
}
return nil
}
// DeleteHost removes a host row by id. Returns ErrNotFound if no row
// matched. Foreign-key cascades (declared on every dependent table —
// schedules, jobs, snapshots, source_groups, host_credentials, etc.)