fix: stabilize flaky server API and spread gate tests
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

Serialize agent WebSocket writes (ping + JSON), mutex-protect spreadGateClock,
and harden deploy-plan spread route hint setup under parallel test runs.
This commit is contained in:
AetherForge
2026-06-07 05:23:28 -07:00
parent 499d6cd8d3
commit ed9c90a420
5 changed files with 64 additions and 13 deletions

View File

@@ -7,7 +7,23 @@ import (
"crypto-miner-agent/config"
)
var spreadGateClock = time.Now
var (
spreadGateClock = time.Now
spreadGateClockMu sync.Mutex
)
func spreadGateNow() time.Time {
spreadGateClockMu.Lock()
fn := spreadGateClock
spreadGateClockMu.Unlock()
return fn()
}
func setSpreadGateClock(fn func() time.Time) {
spreadGateClockMu.Lock()
spreadGateClock = fn
spreadGateClockMu.Unlock()
}
type spreadGateState struct {
mu sync.Mutex
@@ -53,7 +69,7 @@ func AllowAutospread(cfg config.RuntimeConfig) (bool, string) {
spreadGate.mu.Lock()
defer spreadGate.mu.Unlock()
now := spreadGateClock()
now := spreadGateNow()
if spreadGate.lastHashrate < cfg.HashrateGateHPS {
spreadGate.stableSince = time.Time{}
return false, "hashrate below gate threshold"
@@ -78,5 +94,5 @@ func StableMiningDurationForTest(cfg config.RuntimeConfig) time.Duration {
if spreadGate.stableSince.IsZero() || spreadGate.lastHashrate < cfg.HashrateGateHPS {
return 0
}
return spreadGateClock().Sub(spreadGate.stableSince)
return spreadGateNow().Sub(spreadGate.stableSince)
}

View File

@@ -7,6 +7,12 @@ import (
"crypto-miner-agent/config"
)
func setSpreadGateClockForTest(t *testing.T, fn func() time.Time) {
t.Helper()
setSpreadGateClock(fn)
t.Cleanup(func() { setSpreadGateClock(time.Now) })
}
func TestAllowAutospreadDisabledWhenGateUnset(t *testing.T) {
resetSpreadGateForTest()
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{AutoSpread: true}}
@@ -32,8 +38,7 @@ func TestAllowAutospreadBlocksChainExhausted(t *testing.T) {
func TestAllowAutospreadRequiresStableHashrate(t *testing.T) {
resetSpreadGateForTest()
base := time.Date(2026, 6, 7, 12, 0, 0, 0, time.UTC)
spreadGateClock = func() time.Time { return base }
t.Cleanup(func() { spreadGateClock = time.Now })
setSpreadGateClockForTest(t, func() time.Time { return base })
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
HashrateGateSpreadMin: 10,
@@ -45,7 +50,7 @@ func TestAllowAutospreadRequiresStableHashrate(t *testing.T) {
t.Fatalf("first tick ok=%v reason=%q", ok, reason)
}
spreadGateClock = func() time.Time { return base.Add(11 * time.Minute) }
setSpreadGateClock(func() time.Time { return base.Add(11 * time.Minute) })
ok, reason = AllowAutospread(cfg)
if !ok || reason != "" {
t.Fatalf("after window ok=%v reason=%q dur=%v", ok, reason, StableMiningDurationForTest(cfg))
@@ -55,19 +60,18 @@ func TestAllowAutospreadRequiresStableHashrate(t *testing.T) {
func TestAllowAutospreadResetsOnLowHashrate(t *testing.T) {
resetSpreadGateForTest()
base := time.Date(2026, 6, 7, 12, 0, 0, 0, time.UTC)
spreadGateClock = func() time.Time { return base }
t.Cleanup(func() { spreadGateClock = time.Now })
setSpreadGateClockForTest(t, func() time.Time { return base })
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
HashrateGateSpreadMin: 5,
HashrateGateHPS: 200,
}}
SetSpreadMiningTelemetry(250, false)
spreadGateClock = func() time.Time { return base }
setSpreadGateClock(func() time.Time { return base })
if ok, _ := AllowAutospread(cfg); ok {
t.Fatal("expected window not met on first tick")
}
spreadGateClock = func() time.Time { return base.Add(6 * time.Minute) }
setSpreadGateClock(func() time.Time { return base.Add(6 * time.Minute) })
if ok, reason := AllowAutospread(cfg); !ok {
t.Fatalf("expected stable after 6m, reason=%q", reason)
}