From c2459ac3b587bd69a82eb199963f1ede1ccd8cf5 Mon Sep 17 00:00:00 2001 From: Blake Gentry Date: Sat, 5 Oct 2024 10:42:50 -0500 Subject: [PATCH] fix river.JobCancel with nil arg --- CHANGELOG.md | 4 ++++ client_test.go | 30 ++++++++++++++++++++++++++++++ job_executor.go | 3 +++ 3 files changed, 37 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3d6ae20..a61aed0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Breaking change:** The advisory lock unique jobs implementation which was deprecated in v0.12.0 has been removed. Users of that feature should first upgrade to v0.12.1 to ensure they don't see any warning logs about using the deprecated advisory lock uniqueness. The new, faster unique implementation will be used automatically as long as the `UniqueOpts.ByState` list hasn't been customized to remove [required states](https://riverqueue.com/docs/unique-jobs#unique-by-state) (`pending`, `scheduled`, `available`, and `running`). As of this release, customizing `ByState` without these required states returns an error. [PR #614](https://github.com/riverqueue/river/pull/614). - Single job inserts are now unified under the hood to use the `InsertMany` bulk insert query. This should not be noticeable to users, and the unified code path will make it easier to build new features going forward. [PR #614](https://github.com/riverqueue/river/pull/614). +### Fixed + +- Allow `river.JobCancel` to accept a `nil` error as input without panicking. + ## [0.12.1] - 2024-09-26 ### Changed diff --git a/client_test.go b/client_test.go index 8ee79f01..cd9a9908 100644 --- a/client_test.go +++ b/client_test.go @@ -380,6 +380,36 @@ func Test_Client(t *testing.T) { require.WithinDuration(t, time.Now(), *updatedJob.FinalizedAt, 2*time.Second) }) + t.Run("JobCancelErrorReturnedWithNilErr", func(t *testing.T) { + t.Parallel() + + client, _ := setup(t) + + type JobArgs struct { + JobArgsReflectKind[JobArgs] + } + + AddWorker(client.config.Workers, WorkFunc(func(ctx context.Context, job *Job[JobArgs]) error { + return JobCancel(nil) + })) + + subscribeChan := subscribe(t, client) + startClient(ctx, t, client) + + insertRes, err := client.Insert(ctx, &JobArgs{}, nil) + require.NoError(t, err) + + event := riversharedtest.WaitOrTimeout(t, subscribeChan) + require.Equal(t, EventKindJobCancelled, event.Kind) + require.Equal(t, rivertype.JobStateCancelled, event.Job.State) + require.WithinDuration(t, time.Now(), *event.Job.FinalizedAt, 2*time.Second) + + updatedJob, err := client.JobGet(ctx, insertRes.Job.ID) + require.NoError(t, err) + require.Equal(t, rivertype.JobStateCancelled, updatedJob.State) + require.WithinDuration(t, time.Now(), *updatedJob.FinalizedAt, 2*time.Second) + }) + t.Run("JobSnoozeErrorReturned", func(t *testing.T) { t.Parallel() diff --git a/job_executor.go b/job_executor.go index 61669e9d..e1ce5304 100644 --- a/job_executor.go +++ b/job_executor.go @@ -57,6 +57,9 @@ type jobCancelError struct { } func (e *jobCancelError) Error() string { + if e.err == nil { + return "jobCancelError: " + } // should not ever be called, but add a prefix just in case: return "jobCancelError: " + e.err.Error() }