From 2a7292e3aa99818aed40178dd5bba00189f9e112 Mon Sep 17 00:00:00 2001 From: Thomas Jackson Date: Mon, 19 Aug 2019 15:38:24 -0700 Subject: [PATCH] Enforce a min_refresh_duration Before this change a refresh of peers is run on a variety of scenarios-- including any time there is a topology change. In a moderately sized cluster (200+ nodes) there is basically *always* a topology change (connections closing, opening, etc.). Because of this constant state of topology change the mesh ends up constantly updating the peer set effectively in a loop. This patch simply ensures that the refresh happens no more frequently than initialInterval (2s) to avoid this CPU spinning. --- connection_maker.go | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/connection_maker.go b/connection_maker.go index df8d04c..1c011a4 100644 --- a/connection_maker.go +++ b/connection_maker.go @@ -220,8 +220,36 @@ func (cm *connectionMaker) refresh() { } func (cm *connectionMaker) queryLoop(actionChan <-chan connectionMakerAction) { - timer := time.NewTimer(maxDuration) - run := func() { timer.Reset(cm.checkStateAndAttemptConnections()) } + currentDuration := maxDuration + lastRun := time.Time{} + timer := time.NewTimer(currentDuration) + + resetTimer := func(d time.Duration) { + if !timer.Stop() { + select { + case <-timer.C: + } + } + + currentDuration = d + timer.Reset(currentDuration) + } + + run := func() { + now := time.Now() + + // If run() was called too recently, we want to ensure that the duration + // is no longer than initialInterval + if now.Sub(lastRun) < initialInterval { + if currentDuration > initialInterval { + resetTimer(initialInterval) + } + } else { + // otherwise this means we hit the timer + resetTimer(cm.checkStateAndAttemptConnections()) + lastRun = now + } + } for { select { case action := <-actionChan: