diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-23 09:04:17 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-23 09:04:17 +0200 |
| commit | 462184dff3eef32f01f06634305da1355ac1bec2 (patch) | |
| tree | 026ffaaeacfe152957298c985e1df77ff661b723 /internal/stats | |
| parent | 667f2d3384643aa877de2eefcbad3923965bad09 (diff) | |
chore: bump version to v0.25.9v0.25.9
Code quality fixes from audit:
- Log silently discarded errors in status sinks and stats.Update call sites
- Fix json.Marshal errors silently ignored in LSP handlers
- Replace time.Sleep in tests with channel signaling (mcp) and fake clock (stats)
- Make context cancellation work in production time.Sleep sites (handlers_document, cmdentry)
- Remove init()-based provider registration from llm package; use explicit RegisterAllProviders()
- Add WaitGroup goroutine tracking to MCP server Run()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/stats')
| -rw-r--r-- | internal/stats/stats.go | 8 | ||||
| -rw-r--r-- | internal/stats/stats_test.go | 9 |
2 files changed, 14 insertions, 3 deletions
diff --git a/internal/stats/stats.go b/internal/stats/stats.go index d79025a..bd91e20 100644 --- a/internal/stats/stats.go +++ b/internal/stats/stats.go @@ -29,6 +29,10 @@ var windowSeconds int64 = int64(defaultWindow.Seconds()) var errLockWouldBlock = errors.New("stats: lock would block") +// nowFunc is the clock source for event timestamps and pruning cutoffs. +// Replaced in tests to control time without sleeping. +var nowFunc = time.Now + // SetWindow sets the sliding window used for pruning and aggregation. func SetWindow(d time.Duration) { if d < time.Second { @@ -117,7 +121,7 @@ func Update(ctx context.Context, provider, model string, sentBytes, recvBytes in path := filepath.Join(dir, fileName) sf := readStatsFile(path) - now := time.Now() + now := nowFunc() win := Window() sf.WindowSeconds = int(win.Seconds()) sf.Events = append(sf.Events, Event{ @@ -260,7 +264,7 @@ func TakeSnapshot() (Snapshot, error) { if win <= 0 { win = Window() } - cutoff := time.Now().Add(-win) + cutoff := nowFunc().Add(-win) snap := Snapshot{Providers: make(map[string]ProviderEntry), Window: win} for _, ev := range sf.Events { if ev.TS.Before(cutoff) { diff --git a/internal/stats/stats_test.go b/internal/stats/stats_test.go index a9b3d22..47e3068 100644 --- a/internal/stats/stats_test.go +++ b/internal/stats/stats_test.go @@ -33,10 +33,17 @@ func TestUpdate_PrunesOld_ByWindow(t *testing.T) { t.Setenv("XDG_CACHE_HOME", t.TempDir()) SetWindow(2 * time.Second) ctx := context.Background() + + // Inject a fake clock so we can advance time without sleeping. + fakeNow := time.Now() + nowFunc = func() time.Time { return fakeNow } + defer func() { nowFunc = time.Now }() + if err := Update(ctx, "p", "m", 1, 1); err != nil { t.Fatal(err) } - time.Sleep(2200 * time.Millisecond) + // Advance fake time past the 2-second window so the first event is pruned. + fakeNow = fakeNow.Add(3 * time.Second) if err := Update(ctx, "p", "m", 2, 2); err != nil { t.Fatal(err) } |
