From 21fce78ffe97c5ae4472e76bdcf0f978ea3a23b3 Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 4 Apr 2026 19:44:19 +0000 Subject: [PATCH] fix(simple): count upstream errors in stats --- splitter/simple/impl.go | 24 ++++++++++++++++--- splitter/simple/impl_test.go | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/splitter/simple/impl.go b/splitter/simple/impl.go index e7b945f..e79dbcd 100644 --- a/splitter/simple/impl.go +++ b/splitter/simple/impl.go @@ -171,9 +171,27 @@ func (s *SimpleSplitter) Upstreams() proxy.UpstreamStats { s.mu.Lock() defer s.mu.Unlock() var stats proxy.UpstreamStats - stats.Active = uint64(len(s.active)) - stats.Sleep = uint64(len(s.idle)) - stats.Total = stats.Active + stats.Sleep + for _, mapper := range s.active { + if mapper == nil { + continue + } + if mapper.stopped || mapper.strategy == nil || !mapper.strategy.IsActive() { + stats.Error++ + continue + } + stats.Active++ + } + for _, mapper := range s.idle { + if mapper == nil { + continue + } + if mapper.stopped || mapper.strategy == nil || !mapper.strategy.IsActive() { + stats.Error++ + continue + } + stats.Sleep++ + } + stats.Total = stats.Active + stats.Sleep + stats.Error return stats } diff --git a/splitter/simple/impl_test.go b/splitter/simple/impl_test.go index 5fac90e..0ebfaef 100644 --- a/splitter/simple/impl_test.go +++ b/splitter/simple/impl_test.go @@ -66,3 +66,49 @@ func TestSimpleSplitter_OnLogin_Ugly(t *testing.T) { t.Fatalf("expected expired mapper to remain idle until GC, got %d idle mappers", len(splitter.idle)) } } + +func TestSimpleSplitter_Upstreams_Good(t *testing.T) { + splitter := NewSimpleSplitter(&proxy.Config{ReuseTimeout: 30}, nil, func(listener pool.StratumListener) pool.Strategy { + return activeStrategy{} + }) + splitter.active[1] = &SimpleMapper{id: 1, strategy: activeStrategy{}} + splitter.idle[2] = &SimpleMapper{id: 2, strategy: activeStrategy{}, idleAt: time.Now()} + + stats := splitter.Upstreams() + + if stats.Active != 1 { + t.Fatalf("expected one active upstream, got %d", stats.Active) + } + if stats.Sleep != 1 { + t.Fatalf("expected one sleeping upstream, got %d", stats.Sleep) + } + if stats.Error != 0 { + t.Fatalf("expected no error upstreams, got %d", stats.Error) + } + if stats.Total != 2 { + t.Fatalf("expected total upstreams to be 2, got %d", stats.Total) + } +} + +func TestSimpleSplitter_Upstreams_Ugly(t *testing.T) { + splitter := NewSimpleSplitter(&proxy.Config{ReuseTimeout: 30}, nil, func(listener pool.StratumListener) pool.Strategy { + return activeStrategy{} + }) + splitter.active[1] = &SimpleMapper{id: 1, strategy: activeStrategy{}, stopped: true} + splitter.idle[2] = &SimpleMapper{id: 2, strategy: activeStrategy{}, stopped: true, idleAt: time.Now()} + + stats := splitter.Upstreams() + + if stats.Active != 0 { + t.Fatalf("expected no active upstreams, got %d", stats.Active) + } + if stats.Sleep != 0 { + t.Fatalf("expected no sleeping upstreams, got %d", stats.Sleep) + } + if stats.Error != 2 { + t.Fatalf("expected both upstreams to be counted as error, got %d", stats.Error) + } + if stats.Total != 2 { + t.Fatalf("expected total upstreams to be 2, got %d", stats.Total) + } +}