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:
parent
eb822be2e5
commit
9e6348c3b5
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue