From bb2a88be24db1b74f24b60ce02845b7e674a9969 Mon Sep 17 00:00:00 2001 From: Steve Cliff Date: Thu, 7 May 2026 18:46:26 +0100 Subject: [PATCH] ws: record daily repo stats history alongside current upsert --- internal/server/ws/handler.go | 4 +++ internal/server/ws/handler_test.go | 39 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/internal/server/ws/handler.go b/internal/server/ws/handler.go index 5a0473c..4fd0e4c 100644 --- a/internal/server/ws/handler.go +++ b/internal/server/ws/handler.go @@ -339,6 +339,10 @@ func dispatchAgentMessage(ctx context.Context, c *Conn, hostID string, env api.E } else { slog.Info("ws: repo stats refreshed", "host_id", hostID) } + day := time.Now().UTC().Format("2006-01-02") + if err := deps.Store.UpsertHostRepoStatsHistory(ctx, hostID, day, patch, time.Now().UTC()); err != nil { + slog.Warn("ws: upsert host repo stats history", "host_id", hostID, "err", err) + } case api.MsgCommandResult: // TODO(P2): persist command.result acks for "did the agent diff --git a/internal/server/ws/handler_test.go b/internal/server/ws/handler_test.go index 819a812..1bd2088 100644 --- a/internal/server/ws/handler_test.go +++ b/internal/server/ws/handler_test.go @@ -133,3 +133,42 @@ func TestRepoStatsReportPartialUpdate(t *testing.T) { t.Errorf("LastCheckStatus: got %q want ok", got.LastCheckStatus) } } + +func TestRepoStatsReportWritesHistoryRow(t *testing.T) { + t.Parallel() + s := openWSTestStore(t) + ctx := context.Background() + + const hostID = "h-stats-history" + seedHostWS(t, s, hostID) + + payload := api.RepoStatsPayload{ + TotalSizeBytes: int64ptrWS(12345), + SnapshotCount: int64ptrWS(7), + } + env, err := api.Marshal(api.MsgRepoStats, "", payload) + if err != nil { + t.Fatalf("marshal: %v", err) + } + + deps := HandlerDeps{Store: s} + dispatchAgentMessage(ctx, nil, hostID, env, deps) + + pts, err := s.ListHostRepoStatsHistory(ctx, hostID, time.Time{}) + if err != nil { + t.Fatalf("list history: %v", err) + } + if len(pts) != 1 { + t.Fatalf("want 1 history row, got %d", len(pts)) + } + wantDay := time.Now().UTC().Format("2006-01-02") + if got := pts[0].Day.Format("2006-01-02"); got != wantDay { + t.Errorf("day: want %s, got %s", wantDay, got) + } + if pts[0].TotalSizeBytes == nil || *pts[0].TotalSizeBytes != 12345 { + t.Errorf("TotalSizeBytes: want 12345, got %v", pts[0].TotalSizeBytes) + } + if pts[0].SnapshotCount == nil || *pts[0].SnapshotCount != 7 { + t.Errorf("SnapshotCount: want 7, got %v", pts[0].SnapshotCount) + } +}