From 7b0f8b5449e23cb1fb7a73704b84b104569f50cf Mon Sep 17 00:00:00 2001 From: Louis Garman Date: Tue, 13 Aug 2024 21:05:02 +0100 Subject: [PATCH] chore: add before-exited callback to task --- internal/task/spec.go | 4 ++++ internal/task/task.go | 40 ++++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/internal/task/spec.go b/internal/task/spec.go index 4b6d40a5..7da3bdb6 100644 --- a/internal/task/spec.go +++ b/internal/task/spec.go @@ -48,6 +48,10 @@ type Spec struct { // as part of a task group. All specs in the task group must set // InverseDependencyOrder to the same value otherwise an error is raised. InverseDependencyOrder bool + // Call this function before the task has successfully finished. The + // returned string sets the task summary, and the error, if non-nil, deems + // the task to have failed and places the task into an errored state. + BeforeExited func(*Task) (string, error) // Call this function after the task has successfully finished AfterExited func(*Task) // Call this function after the task is enqueued. diff --git a/internal/task/task.go b/internal/task/task.go index 43fa0e5e..f384a3ec 100644 --- a/internal/task/task.go +++ b/internal/task/task.go @@ -30,7 +30,9 @@ type Task struct { Immediate bool AdditionalEnv []string DependsOn []resource.ID - description string + // Summary summarises the outcome of a task to the end-user. + Summary string + description string program string exclusive bool @@ -63,24 +65,15 @@ type Task struct { // the task can be retried. Spec Spec - // Call this function after the task has successfully finished - AfterExited func(*Task) - // Call this function after the task is enqueued. - AfterQueued func(*Task) - // Call this function after the task starts running. - AfterRunning func(*Task) - // Call this function after the task fails with an error - AfterError func(*Task) - // Call this function after the task is successfully canceled + BeforeExited func(*Task) (string, error) + AfterExited func(*Task) + AfterQueued func(*Task) + AfterRunning func(*Task) + AfterError func(*Task) AfterCanceled func(*Task) - // Call this function after the task terminates for whatever reason. - AfterFinish func(*Task) - - // call this whenever state is updated - afterUpdate func(*Task) - - // call this once the task has terminated - afterFinish func(*Task) + AfterFinish func(*Task) + afterUpdate func(*Task) + afterFinish func(*Task) } type factory struct { @@ -132,6 +125,8 @@ func (f *factory) newTask(spec Spec) *Task { AfterFinish: spec.AfterFinish, // Publish an event whenever task state is updated afterUpdate: func(t *Task) { + // TODO: remove nil-check that is only here to ensure tests don't + // have to mock publisher... if f.publisher != nil { f.publisher.Publish(resource.UpdatedEvent, t) } @@ -288,6 +283,15 @@ func (t *Task) updateState(state Status) { t.timestamps[state] = statusTimestamps{ started: now, } + // Before task exits trigger callback and if it fails set task's status to + // errored. Otherwise the returned summary summarises the task's outcome. + if state == Exited && t.BeforeExited != nil { + summary, err := t.BeforeExited(t) + if err != nil { + state = Errored + } + t.Summary = summary + } t.State = state if t.afterUpdate != nil {