fix: resolve issue number 463

Resolved original issue by introducing a boolean chanel by which exechook runner can communicate with main thread.
Then introduced and used webhook executed-at-least-once chanel and added documentation explaining sections of of code
only executed when git-sync pulls for first time.
This commit is contained in:
ChrisERo 2022-01-07 20:02:39 -05:00 committed by chrrodri
parent eb822be2e5
commit 9e6348c3b5
2 changed files with 42 additions and 2 deletions

View File

@ -174,6 +174,9 @@ 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
const (
metricKeySuccess = "success"
metricKeyError = "error"
@ -359,6 +362,8 @@ func main() {
if *flExechookBackoff < time.Second {
handleError(log, true, "ERROR: --exechook-backoff must be at least 1s")
}
execHookChannel = make(chan bool)
}
if *flWebhookURL != "" {
@ -371,6 +376,8 @@ func main() {
if *flWebhookBackoff < time.Second {
handleError(log, true, "ERROR: --webhook-backoff must be at least 1s")
}
webHookChannel = make(chan bool)
}
if *flPassword != "" && *flPasswordFile != "" {
@ -556,6 +563,7 @@ func main() {
*flWebhookBackoff,
hook.NewHookData(),
log,
webHookChannel,
)
go webhookRunner.Run(context.Background())
}
@ -576,6 +584,7 @@ func main() {
*flExechookBackoff,
hook.NewHookData(),
log,
execHookChannel,
)
go exechookRunner.Run(context.Background())
}
@ -621,6 +630,22 @@ func main() {
}
if initialSync {
// Wait for hooks to complete at least once before checking whether to stop
// 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 {
log.Error(nil, "exec hook completed with error")
}
}
if webHookChannel != nil {
webHookChannelFinishedSuccessfully:= <-webHookChannel
if !webHookChannelFinishedSuccessfully {
log.Error(nil, "web hook completed with error")
}
}
// Determine if git-sync should terminate
if *flOneTime {
log.DeleteErrorFile()
os.Exit(0)

View File

@ -82,8 +82,8 @@ func (d *hookData) send(newHash string) {
}
// NewHookRunner returns a new HookRunner
func NewHookRunner(hook Hook, backoff time.Duration, data *hookData, log *logging.Logger) *HookRunner {
return &HookRunner{hook: hook, backoff: backoff, data: data, logger: log}
func NewHookRunner(hook Hook, backoff time.Duration, data *hookData, log *logging.Logger, hasSucceededOnce chan bool) *HookRunner {
return &HookRunner{hook: hook, backoff: backoff, data: data, logger: log, hasCompletedOnce: hasSucceededOnce}
}
// HookRunner struct
@ -96,6 +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 chan bool
}
// Send sends hash to hookdata
@ -123,16 +125,29 @@ func (r *HookRunner) Run(ctx context.Context) {
if err := r.hook.Do(ctx, hash); err != nil {
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)
time.Sleep(r.backoff)
} else {
updateHookRunCountMetric(r.hook.Name(), "success")
lastHash = hash
r.sendCompletedOnceMessage(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 r.hasCompletedOnce != nil {
r.hasCompletedOnce <- completedSuccessfully
close(r.hasCompletedOnce)
r.hasCompletedOnce = nil
}
}
func updateHookRunCountMetric(name, status string) {
hookRunCount.WithLabelValues(name, status).Inc()
}