fix: addressed several concers raised by thockin

- Renamed [x]HookChannel to [x]hookChannel for consistency
- Made hookChannels buffered chanels of size 1
- Added clarifying documentation and renamed functions expalining how I was
    - ensuring that hooks execute at least once, assuming that main thread does not crash
    - make sure chanels are not written to more than once
This commit is contained in:
ChrisERo 2022-01-08 14:36:22 -05:00 committed by chrrodri
parent 9e6348c3b5
commit 3b5ed549eb
2 changed files with 23 additions and 21 deletions

View File

@ -174,8 +174,10 @@ var (
}, []string{"status"})
)
// Channels for ensuring hooks execute at least once before terminating due to GIT_SYNC_ONCE
var execHookChannel, webHookChannel chan bool // initialising as null to promptly catch logical errors and to avoid unneeded object creation
// Channels for ensuring hooks execute at least once before terminating.
// Should be nil if and only if corresponding hook is not defined and if initialised, will only every get written
// to once.
var exechookChannel, webhookChannel chan bool
const (
metricKeySuccess = "success"
@ -362,8 +364,7 @@ func main() {
if *flExechookBackoff < time.Second {
handleError(log, true, "ERROR: --exechook-backoff must be at least 1s")
}
execHookChannel = make(chan bool)
exechookChannel = make(chan bool, 1)
}
if *flWebhookURL != "" {
@ -376,8 +377,7 @@ func main() {
if *flWebhookBackoff < time.Second {
handleError(log, true, "ERROR: --webhook-backoff must be at least 1s")
}
webHookChannel = make(chan bool)
webhookChannel = make(chan bool, 1)
}
if *flPassword != "" && *flPasswordFile != "" {
@ -563,7 +563,7 @@ func main() {
*flWebhookBackoff,
hook.NewHookData(),
log,
webHookChannel,
webhookChannel,
)
go webhookRunner.Run(context.Background())
}
@ -584,7 +584,7 @@ func main() {
*flExechookBackoff,
hook.NewHookData(),
log,
execHookChannel,
exechookChannel,
)
go exechookRunner.Run(context.Background())
}
@ -630,17 +630,17 @@ func main() {
}
if initialSync {
// Wait for hooks to complete at least once before checking whether to stop
// Wait for hooks to complete at least once, if not nil, before checking whether to stop program
// Assumes that if hook channels are not nil, they will have at least one value before getting closed
if execHookChannel != nil {
execHookChannelFinishedSuccessfully:= <-execHookChannel
if !execHookChannelFinishedSuccessfully {
if exechookChannel != nil {
exechookChannelFinishedSuccessfully := <-exechookChannel
if !exechookChannelFinishedSuccessfully {
log.Error(nil, "exec hook completed with error")
}
}
if webHookChannel != nil {
webHookChannelFinishedSuccessfully:= <-webHookChannel
if !webHookChannelFinishedSuccessfully {
if webhookChannel != nil {
webhookChannelFinishedSuccessfully := <-webhookChannel
if !webhookChannelFinishedSuccessfully {
log.Error(nil, "web hook completed with error")
}
}

View File

@ -96,7 +96,8 @@ type HookRunner struct {
data *hookData
// Logger
logger *logging.Logger
// Has succeeded once Chanel, sends true if first run executed successfully and false if it failed
// hasCompletedOnce is used to send true if and only if first run executed successfully and false otherwise to some receiver.
// should be initialised to a buffered channel of size 1. Is only meant to be used within sendCompletedOnceMessageIfApplicable
hasCompletedOnce chan bool
}
@ -126,21 +127,22 @@ func (r *HookRunner) Run(ctx context.Context) {
r.logger.Error(err, "hook failed")
updateHookRunCountMetric(r.hook.Name(), "error")
// don't want to sleep unnecessarily if we are going to terminate anyways
r.sendCompletedOnceMessage(false)
r.sendCompletedOnceMessageIfApplicable(false)
time.Sleep(r.backoff)
} else {
updateHookRunCountMetric(r.hook.Name(), "success")
lastHash = hash
r.sendCompletedOnceMessage(true)
r.sendCompletedOnceMessageIfApplicable(true)
break
}
}
}
}
// sendCompletedOnceMessage forwards the success status (as a boolean) of the first execution of HookRunner, the first time
// to the r.hasCompletedOnce channel
func (r *HookRunner) sendCompletedOnceMessage(completedSuccessfully bool) {
// If hasCompletedOnce is nil, does nothing. Otherwise, forwards the caller provided success status (as a boolean) of
// HookRunner to receivers of hasCompletedOnce, closes said chanel, and sets hasCompletedOnce to nil.
// Using this function to write to hasCompletedOnce ensures it is only every written to once.
func (r *HookRunner) sendCompletedOnceMessageIfApplicable(completedSuccessfully bool) {
if r.hasCompletedOnce != nil {
r.hasCompletedOnce <- completedSuccessfully
close(r.hasCompletedOnce)