github.com/dkerwin/nomad@v0.3.3-0.20160525181927-74554135514b/client/consul/check.go (about) 1 package consul 2 3 import ( 4 "log" 5 "math/rand" 6 "sync" 7 "time" 8 9 cstructs "github.com/hashicorp/nomad/client/driver/structs" 10 ) 11 12 // CheckRunner runs a given check in a specific interval and update a 13 // corresponding Consul TTL check 14 type CheckRunner struct { 15 check Check 16 runCheck func(Check) 17 logger *log.Logger 18 stop bool 19 stopCh chan struct{} 20 stopLock sync.Mutex 21 22 started bool 23 startedLock sync.Mutex 24 } 25 26 // NewCheckRunner configures and returns a CheckRunner 27 func NewCheckRunner(check Check, runCheck func(Check), logger *log.Logger) *CheckRunner { 28 cr := CheckRunner{ 29 check: check, 30 runCheck: runCheck, 31 logger: logger, 32 stopCh: make(chan struct{}), 33 } 34 return &cr 35 } 36 37 // Start is used to start the check. The check runs until stop is called 38 func (r *CheckRunner) Start() { 39 r.startedLock.Lock() 40 defer r.startedLock.Unlock() 41 if r.started { 42 return 43 } 44 r.stopLock.Lock() 45 defer r.stopLock.Unlock() 46 go r.run() 47 r.started = true 48 } 49 50 // Stop is used to stop the check. 51 func (r *CheckRunner) Stop() { 52 r.stopLock.Lock() 53 defer r.stopLock.Unlock() 54 if !r.stop { 55 r.stop = true 56 close(r.stopCh) 57 } 58 } 59 60 // run is invoked by a goroutine to run until Stop() is called 61 func (r *CheckRunner) run() { 62 // Get the randomized initial pause time 63 initialPauseTime := randomStagger(r.check.Interval()) 64 r.logger.Printf("[DEBUG] agent: pausing %v before first invocation of %s", initialPauseTime, r.check.ID()) 65 next := time.NewTimer(initialPauseTime) 66 for { 67 select { 68 case <-next.C: 69 r.runCheck(r.check) 70 next.Reset(r.check.Interval()) 71 case <-r.stopCh: 72 next.Stop() 73 return 74 } 75 } 76 } 77 78 // Check is an interface which check providers can implement for Nomad to run 79 type Check interface { 80 Run() *cstructs.CheckResult 81 ID() string 82 Interval() time.Duration 83 Timeout() time.Duration 84 } 85 86 // Returns a random stagger interval between 0 and the duration 87 func randomStagger(intv time.Duration) time.Duration { 88 return time.Duration(uint64(rand.Int63()) % uint64(intv)) 89 }