From 08c47632f023acec8b43ea8bfae1729584f95860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Villaf=C3=A1=C3=B1ez?= Date: Mon, 22 Apr 2024 12:51:25 +0200 Subject: [PATCH] fix: use custom timeout error if the runner times out --- ocis-pkg/runner/runner.go | 3 +-- ocis-pkg/runner/runner_test.go | 6 +++++- ocis-pkg/runner/types.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/ocis-pkg/runner/runner.go b/ocis-pkg/runner/runner.go index 79b93cc54b..ced99cc8b0 100644 --- a/ocis-pkg/runner/runner.go +++ b/ocis-pkg/runner/runner.go @@ -2,7 +2,6 @@ package runner import ( "context" - "fmt" "sync/atomic" "time" ) @@ -188,7 +187,7 @@ func (r *Runner) doTask(ch chan<- *Result, closeChan bool) { case d := <-r.interruptedCh: result = &Result{ RunnerID: r.ID, - RunnerError: fmt.Errorf("runner %s timed out after waiting for %s", r.ID, d.String()), + RunnerError: NewTimeoutError(r.ID, d), } case result = <-tmpCh: // Just assign the received value, nothing else to do diff --git a/ocis-pkg/runner/runner_test.go b/ocis-pkg/runner/runner_test.go index 7198e83d01..b44e398eb6 100644 --- a/ocis-pkg/runner/runner_test.go +++ b/ocis-pkg/runner/runner_test.go @@ -181,7 +181,11 @@ var _ = Describe("Runner", func() { // context is done), so test should finish in 4 seconds Eventually(ctx, ch2).Should(Receive(&expectedResult)) Expect(expectedResult.RunnerID).To(Equal("run003")) - Expect(expectedResult.RunnerError.Error()).To(ContainSubstring("timed out")) + + var timeoutError *runner.TimeoutError + Expect(errors.As(expectedResult.RunnerError, &timeoutError)).To(BeTrue()) + Expect(timeoutError.RunnerID).To(Equal("run003")) + Expect(timeoutError.Duration).To(Equal(3 * time.Second)) }, SpecTimeout(5*time.Second)) It("Run mutiple times panics", func(ctx SpecContext) { diff --git a/ocis-pkg/runner/types.go b/ocis-pkg/runner/types.go index 4cce8d6bdf..2789838c65 100644 --- a/ocis-pkg/runner/types.go +++ b/ocis-pkg/runner/types.go @@ -1,5 +1,10 @@ package runner +import ( + "strings" + "time" +) + // Runable represent a task that can be executed by the Runner. // It expected to be a long running task with an indefinite execution time, // so it's suitable for servers or services. @@ -33,3 +38,29 @@ type Result struct { RunnerID string RunnerError error } + +// TimeoutError is an error that should be used for timeouts. +// It implements the `error` interface +type TimeoutError struct { + RunnerID string + Duration time.Duration +} + +// NewTimeoutError creates a new timeout error. Both runnerID and duration +// will be used in the error message +func NewTimeoutError(runnerID string, duration time.Duration) *TimeoutError { + return &TimeoutError{ + RunnerID: runnerID, + Duration: duration, + } +} + +// Error generates the message for this particular error. +func (te *TimeoutError) Error() string { + var sb strings.Builder + sb.WriteString("Runner ") + sb.WriteString(te.RunnerID) + sb.WriteString(" timed out after waiting for ") + sb.WriteString(te.Duration.String()) + return sb.String() +}