From a43935308e893ec5eac7b889548ac2b8ad330683 Mon Sep 17 00:00:00 2001 From: clawbot <35+clawbot@noreply.example.org> Date: Wed, 14 Oct 2026 15:59:15 +0200 Subject: [PATCH] Count every reconnect in reconnect_count (closes #68) `reconnect_count` in `/api/v1/stats` stayed 0 however often the stream reconnected: `SetConnected` counted a reconnect only while the stream was still marked connected, and the streamer always marks it disconnected first. It now counts one reconnect for every connection after the first, recognised by the zero `connectedSince` before the first connection. A test connects and disconnects twice and expects 2. Model: opus-5-5 --- internal/metrics/metrics.go | 25 +++++++++++++++---------- internal/metrics/metrics_test.go | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 internal/metrics/metrics_test.go diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index 86f2057..25aef45 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -60,17 +60,22 @@ func New() *Tracker { } } -// SetConnected updates the connection status +// SetConnected updates the connection status. Every connection after the +// first counts one reconnect. func (t *Tracker) SetConnected(connected bool) { - wasConnected := t.isConnected.Swap(connected) - if connected { - t.mu.Lock() - t.connectedSince = time.Now() - t.mu.Unlock() - // Increment reconnect count (but not for the initial connection) - if wasConnected || t.reconnectCount.Load() > 0 { - t.reconnectCount.Add(1) - } + t.isConnected.Store(connected) + if !connected { + return + } + + t.mu.Lock() + // connectedSince is zero until the first connection. + connectedBefore := !t.connectedSince.IsZero() + t.connectedSince = time.Now() + t.mu.Unlock() + + if connectedBefore { + t.reconnectCount.Add(1) } } diff --git a/internal/metrics/metrics_test.go b/internal/metrics/metrics_test.go new file mode 100644 index 0000000..e8776fd --- /dev/null +++ b/internal/metrics/metrics_test.go @@ -0,0 +1,21 @@ +package metrics + +import "testing" + +// TestReconnectCount connects three times with a disconnect between each, the +// way the streamer does, and expects every connection after the first to count +// one reconnect. +func TestReconnectCount(t *testing.T) { + tracker := New() + + tracker.SetConnected(true) + tracker.SetConnected(false) + tracker.SetConnected(true) + tracker.SetConnected(false) + tracker.SetConnected(true) + + const wantReconnects = 2 + if got := tracker.GetReconnectCount(); got != wantReconnects { + t.Fatalf("reconnect count = %d, want %d", got, wantReconnects) + } +}