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

View File

@ -96,7 +96,8 @@ type HookRunner struct {
data *hookData data *hookData
// Logger // Logger
logger *logging.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 hasCompletedOnce chan bool
} }
@ -126,21 +127,22 @@ func (r *HookRunner) Run(ctx context.Context) {
r.logger.Error(err, "hook failed") r.logger.Error(err, "hook failed")
updateHookRunCountMetric(r.hook.Name(), "error") updateHookRunCountMetric(r.hook.Name(), "error")
// don't want to sleep unnecessarily if we are going to terminate anyways // don't want to sleep unnecessarily if we are going to terminate anyways
r.sendCompletedOnceMessage(false) r.sendCompletedOnceMessageIfApplicable(false)
time.Sleep(r.backoff) time.Sleep(r.backoff)
} else { } else {
updateHookRunCountMetric(r.hook.Name(), "success") updateHookRunCountMetric(r.hook.Name(), "success")
lastHash = hash lastHash = hash
r.sendCompletedOnceMessage(true) r.sendCompletedOnceMessageIfApplicable(true)
break break
} }
} }
} }
} }
// sendCompletedOnceMessage forwards the success status (as a boolean) of the first execution of HookRunner, the first time // If hasCompletedOnce is nil, does nothing. Otherwise, forwards the caller provided success status (as a boolean) of
// to the r.hasCompletedOnce channel // HookRunner to receivers of hasCompletedOnce, closes said chanel, and sets hasCompletedOnce to nil.
func (r *HookRunner) sendCompletedOnceMessage(completedSuccessfully bool) { // 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 { if r.hasCompletedOnce != nil {
r.hasCompletedOnce <- completedSuccessfully r.hasCompletedOnce <- completedSuccessfully
close(r.hasCompletedOnce) close(r.hasCompletedOnce)