github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/memberlist/awareness.go (about) 1 package memberlist 2 3 import ( 4 "sync" 5 "time" 6 7 "github.com/armon/go-metrics" 8 ) 9 10 // awareness manages a simple metric for tracking the estimated health of the 11 // local node. Health is primary the node's ability to respond in the soft 12 // real-time manner required for correct health checking of other nodes in the 13 // cluster. 14 type awareness struct { 15 sync.RWMutex 16 17 // max is the upper threshold for the timeout scale (the score will be 18 // constrained to be from 0 <= score < max). 19 max int 20 21 // score is the current awareness score. Lower values are healthier and 22 // zero is the minimum value. 23 score int 24 } 25 26 // newAwareness returns a new awareness object. 27 func newAwareness(max int) *awareness { 28 return &awareness{ 29 max: max, 30 score: 0, 31 } 32 } 33 34 // ApplyDelta takes the given delta and applies it to the score in a thread-safe 35 // manner. It also enforces a floor of zero and a max of max, so deltas may not 36 // change the overall score if it's railed at one of the extremes. 37 func (a *awareness) ApplyDelta(delta int) { 38 a.Lock() 39 initial := a.score 40 a.score += delta 41 if a.score < 0 { 42 a.score = 0 43 } else if a.score > (a.max - 1) { 44 a.score = (a.max - 1) 45 } 46 final := a.score 47 a.Unlock() 48 49 if initial != final { 50 metrics.SetGauge([]string{"memberlist", "health", "score"}, float32(final)) 51 } 52 } 53 54 // GetHealthScore returns the raw health score. 55 func (a *awareness) GetHealthScore() int { 56 a.RLock() 57 score := a.score 58 a.RUnlock() 59 return score 60 } 61 62 // ScaleTimeout takes the given duration and scales it based on the current 63 // score. Less healthyness will lead to longer timeouts. 64 func (a *awareness) ScaleTimeout(timeout time.Duration) time.Duration { 65 a.RLock() 66 score := a.score 67 a.RUnlock() 68 return timeout * (time.Duration(score) + 1) 69 }