fix: project finished backup jobs onto host row + smoke path tweaks
CI / Test (store) (pull_request) Successful in 50s
CI / Test (rest) (pull_request) Successful in 1m5s
CI / Lint (pull_request) Successful in 24s
CI / Build (linux/amd64) (pull_request) Successful in 22s
CI / Build (windows/amd64) (pull_request) Successful in 43s
CI / Test (server-http) (pull_request) Successful in 1m51s
CI / Build (linux/arm64) (pull_request) Successful in 21s
CI / Test (store) (pull_request) Successful in 50s
CI / Test (rest) (pull_request) Successful in 1m5s
CI / Lint (pull_request) Successful in 24s
CI / Build (linux/amd64) (pull_request) Successful in 22s
CI / Build (windows/amd64) (pull_request) Successful in 43s
CI / Test (server-http) (pull_request) Successful in 1m51s
CI / Build (linux/arm64) (pull_request) Successful in 21s
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:
@@ -38,7 +38,7 @@ but the **agent** is fetched by the install script from the server's
|
|||||||
**install script** are fetched from `<DataDir>/install/`. Plain
|
**install script** are fetched from `<DataDir>/install/`. Plain
|
||||||
`make build` doesn't touch any of those — the source-of-truth files
|
`make build` doesn't touch any of those — the source-of-truth files
|
||||||
in the working tree (`deploy/install/*`, `bin/restic-manager-agent`)
|
in the working tree (`deploy/install/*`, `bin/restic-manager-agent`)
|
||||||
must be copied into `/tmp/rm-smoke/data/...` *and* the running agent
|
must be copied into `$HOME/smoke/data/...` *and* the running agent
|
||||||
on this dev host needs replacing if the change touches agent code or
|
on this dev host needs replacing if the change touches agent code or
|
||||||
the unit file.
|
the unit file.
|
||||||
|
|
||||||
@@ -53,13 +53,13 @@ asking the operator to test.**
|
|||||||
```sh
|
```sh
|
||||||
# 1. Restage what the install script serves (binary + unit + script).
|
# 1. Restage what the install script serves (binary + unit + script).
|
||||||
cp bin/restic-manager-agent \
|
cp bin/restic-manager-agent \
|
||||||
/tmp/rm-smoke/data/agent-binaries/restic-manager-agent-linux-amd64
|
$HOME/smoke/data/agent-binaries/restic-manager-agent-linux-amd64
|
||||||
cp deploy/install/install.sh \
|
cp deploy/install/install.sh \
|
||||||
/tmp/rm-smoke/data/install/install.sh
|
$HOME/smoke/data/install/install.sh
|
||||||
cp deploy/install/install.ps1 \
|
cp deploy/install/install.ps1 \
|
||||||
/tmp/rm-smoke/data/install/install.ps1
|
$HOME/smoke/data/install/install.ps1
|
||||||
cp deploy/install/restic-manager-agent.service \
|
cp deploy/install/restic-manager-agent.service \
|
||||||
/tmp/rm-smoke/data/install/restic-manager-agent.service
|
$HOME/smoke/data/install/restic-manager-agent.service
|
||||||
|
|
||||||
# 2. Replace the running agent on this dev box and restart the
|
# 2. Replace the running agent on this dev box and restart the
|
||||||
# service. Skip only when the change is server-side only AND
|
# service. Skip only when the change is server-side only AND
|
||||||
@@ -74,11 +74,11 @@ sudo -n systemctl restart restic-manager-agent
|
|||||||
# 3. The server runs from the working tree; restart it manually
|
# 3. The server runs from the working tree; restart it manually
|
||||||
# after a build that touches server code:
|
# after a build that touches server code:
|
||||||
pkill -f restic-manager-server
|
pkill -f restic-manager-server
|
||||||
RM_LISTEN=:8080 RM_DATA_DIR=/tmp/rm-smoke/data \
|
RM_LISTEN=:8080 RM_DATA_DIR=$HOME/smoke/data \
|
||||||
RM_BASE_URL=http://127.0.0.1:8080 \
|
RM_BASE_URL=http://127.0.0.1:8080 \
|
||||||
RM_SECRET_KEY_FILE=/tmp/rm-smoke/data/secret.key \
|
RM_SECRET_KEY_FILE=$HOME/smoke/data/secret.key \
|
||||||
RM_COOKIE_SECURE=false \
|
RM_COOKIE_SECURE=false \
|
||||||
./bin/restic-manager-server >> /tmp/rm-smoke/server.log 2>&1 &
|
./bin/restic-manager-server >> $HOME/smoke/server.log 2>&1 &
|
||||||
```
|
```
|
||||||
|
|
||||||
A `make smoke-deploy` target that bundles all of this would be a
|
A `make smoke-deploy` target that bundles all of this would be a
|
||||||
|
|||||||
@@ -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
|
// a *success* — restic's idempotent init returns that when the
|
||||||
// repo is already initialised, which is the happy path for
|
// repo is already initialised, which is the happy path for
|
||||||
// onboarding against an existing repo.
|
// onboarding against an existing repo.
|
||||||
if job, err := deps.Store.GetJob(ctx, p.JobID); err == nil && job != nil &&
|
if job, err := deps.Store.GetJob(ctx, p.JobID); err == nil && job != nil {
|
||||||
job.Kind == string(api.JobInit) {
|
switch job.Kind {
|
||||||
status, errOut := repoStatusFromInit(string(p.Status), errMsg)
|
case string(api.JobInit):
|
||||||
if err := deps.Store.SetHostRepoStatus(ctx, hostID, status, errOut); err != nil {
|
status, errOut := repoStatusFromInit(string(p.Status), errMsg)
|
||||||
slog.Warn("ws: set host repo status", "host_id", hostID, "err", err)
|
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 {
|
if deps.JobHub != nil {
|
||||||
|
|||||||
@@ -81,6 +81,19 @@ func (s *Store) SetHostRepoStatus(ctx context.Context, hostID, status, errMsg st
|
|||||||
return nil
|
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
|
// DeleteHost removes a host row by id. Returns ErrNotFound if no row
|
||||||
// matched. Foreign-key cascades (declared on every dependent table —
|
// matched. Foreign-key cascades (declared on every dependent table —
|
||||||
// schedules, jobs, snapshots, source_groups, host_credentials, etc.)
|
// schedules, jobs, snapshots, source_groups, host_credentials, etc.)
|
||||||
|
|||||||
Reference in New Issue
Block a user