-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement script checks #986
Changes from 18 commits
4faf16b
42dc8be
2b60e8b
1e4da82
f1cf87b
e8995be
588666d
fe9e271
52d4b01
8342d7d
62249fe
12dc439
52f7f93
0fed52c
9a27bf4
e866d3b
7454ffd
4c27660
f8db6a4
bfc2a0d
e0b9f03
644710a
f1d9b2c
d4a5f07
6ee99af
59e91e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package consul | ||
|
||
import ( | ||
"log" | ||
"math/rand" | ||
"sync" | ||
"time" | ||
|
||
cstructs "github.com/hashicorp/nomad/client/driver/structs" | ||
) | ||
|
||
// CheckRunner runs a given check in a specific interval and update a | ||
// corresponding Consul TTL check | ||
type CheckRunner struct { | ||
check Check | ||
runCheck func(Check) | ||
logger *log.Logger | ||
stop bool | ||
stopCh chan struct{} | ||
stopLock sync.Mutex | ||
|
||
started bool | ||
startedLock sync.Mutex | ||
} | ||
|
||
// NewCheckRunner configures and returns a CheckRunner | ||
func NewCheckRunner(check Check, runCheck func(Check), logger *log.Logger) *CheckRunner { | ||
cr := CheckRunner{ | ||
check: check, | ||
runCheck: runCheck, | ||
logger: logger, | ||
stopCh: make(chan struct{}), | ||
} | ||
return &cr | ||
} | ||
|
||
// Start is used to start the check. The check runs until stop is called | ||
func (r *CheckRunner) Start() { | ||
r.startedLock.Lock() | ||
defer r.startedLock.Unlock() | ||
if r.started { | ||
return | ||
} | ||
r.stopLock.Lock() | ||
defer r.stopLock.Unlock() | ||
go r.run() | ||
r.started = true | ||
} | ||
|
||
// Stop is used to stop the check. | ||
func (r *CheckRunner) Stop() { | ||
r.stopLock.Lock() | ||
defer r.stopLock.Unlock() | ||
if !r.stop { | ||
r.stop = true | ||
close(r.stopCh) | ||
} | ||
} | ||
|
||
// run is invoked by a goroutine to run until Stop() is called | ||
func (r *CheckRunner) run() { | ||
// Get the randomized initial pause time | ||
initialPauseTime := randomStagger(r.check.Interval()) | ||
r.logger.Printf("[DEBUG] agent: pausing %v before first invocation of %s", initialPauseTime, r.check.ID()) | ||
next := time.After(initialPauseTime) | ||
for { | ||
select { | ||
case <-next: | ||
r.runCheck(r.check) | ||
next = time.After(r.check.Interval()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dadgar Can't use a single timer or ticker here since we are sleeping for a different duration for the first time, and from then onwards sleeping for the duration of the check interval. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes you can: https://golang.org/pkg/time/#Timer.Reset Reset takes a duration There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh cool. |
||
case <-r.stopCh: | ||
return | ||
} | ||
} | ||
} | ||
|
||
// Check is an interface which check providers can implement for Nomad to run | ||
type Check interface { | ||
Run() *cstructs.CheckResult | ||
ID() string | ||
Interval() time.Duration | ||
} | ||
|
||
// Returns a random stagger interval between 0 and the duration | ||
func randomStagger(intv time.Duration) time.Duration { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a duplicate from somewhere. Can you put it in a utils package or something to share? |
||
return time.Duration(uint64(rand.Int63()) % uint64(intv)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are creating a lot of timers. Just outside the for loop create one https://golang.org/pkg/time/#NewTimer and then use
sync.Reset()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a Ticker would be more appropriate.