Defer dashboard RPCs until after ckpool notifier completes on tip change

On ZMQ hashblock events, wait for the ckpool "Block update latency"
log line before firing dashboard RPC calls (getblockchaininfo,
getnetworkhashps, etc). This avoids competing with ckpool's
latency-critical getblocktemplate call for bitcoind RPC threads,
which matters when many services flood bitcoind on every new block.
This commit is contained in:
satoshi
2026-05-18 17:53:50 +03:00
parent 1157f3501a
commit c6f0ba5f4d
2 changed files with 34 additions and 6 deletions
+28 -6
View File
@@ -270,6 +270,13 @@ type Aggregator struct {
latencyLastMs int64 // most recent observation
staleWorkHashes float64 // cumulative wasted hashes = sum(latency_s * hashrate_at_event)
// notifierDone is signalled by IngestLatencyEvents when a latency
// event arrives, meaning ckpool's notifier has finished its
// getblocktemplate + mining.notify cycle. The Run loop uses this to
// defer dashboard RPC calls until after the notifier is done,
// avoiding resource contention on bitcoind.
notifierDone chan struct{}
// High-water mark for the best share difficulty ever seen.
// Persisted to kv so it survives restarts and transient ckpool gaps.
bestDiff float64
@@ -296,13 +303,14 @@ type Aggregator struct {
func New(ck *ckpool.Client, rpc *bitcoind.RPC, interval time.Duration, log *slog.Logger) *Aggregator {
return &Aggregator{
CK: ck,
RPC: rpc,
Interval: interval,
Log: log,
CK: ck,
RPC: rpc,
Interval: interval,
Log: log,
sessionRejectReasons: make(map[string]int64),
alltimeRejectReasons: make(map[string]int64),
ready: make(chan struct{}),
ready: make(chan struct{}),
notifierDone: make(chan struct{}, 1),
}
}
@@ -345,7 +353,21 @@ func (a *Aggregator) Run(ctx context.Context, tipEvents <-chan zmqmon.TipEvent)
a.mu.Lock()
a.lastZMQEventTime = ev.SeenAt
a.mu.Unlock()
a.Log.Debug("zmq tip, refreshing", "hash", ev.Hash)
// Wait for ckpool's notifier to finish (getblocktemplate +
// mining.notify) before firing our dashboard RPCs, so we
// don't compete for bitcoind RPC resources during the
// latency-critical window. The latency log line signals
// completion. Timeout after 5s in case the log line is
// missed or ckpool is slow.
a.Log.Debug("zmq tip, waiting for notifier", "hash", ev.Hash)
select {
case <-a.notifierDone:
a.Log.Debug("notifier done, refreshing dashboard")
case <-time.After(5 * time.Second):
a.Log.Debug("notifier wait timed out, refreshing anyway")
case <-ctx.Done():
return
}
a.refresh(ctx)
}
}