Skip to content

Commit d2d0ee9

Browse files
committed
Keep the original job object when using retry_job
When the job is retried, we want to preserve the original `scheduled_at`, `queue_name` and `priority`. Instead of using `dup`, this copies and restores the necessary attributes.
1 parent e31e761 commit d2d0ee9

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

activejob/lib/active_job/exceptions.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,10 @@ def after_discard(&blk)
157157
# end
158158
def retry_job(options = {})
159159
instrument :enqueue_retry, options.slice(:error, :wait) do
160-
job = dup
161-
job.enqueue options
160+
scheduled_at, queue_name, priority = self.scheduled_at, self.queue_name, self.priority
161+
enqueue options
162+
ensure
163+
self.scheduled_at, self.queue_name, self.priority = scheduled_at, queue_name, priority
162164
end
163165
end
164166

activejob/test/cases/exceptions_test.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require "helper"
44
require "jobs/retry_job"
5+
require "jobs/retries_job"
56
require "jobs/after_discard_retry_job"
67
require "models/person"
78
require "minitest/mock"
@@ -343,6 +344,13 @@ def adapter_skips_scheduling?(queue_adapter)
343344
assert_equal ["Raised DefaultsError for the 5th time"], JobBuffer.values
344345
end
345346

347+
test "retrying a job when before_enqueue raised uses the same job object" do
348+
job = RetriesJob.new
349+
assert_nothing_raised do
350+
job.enqueue
351+
end
352+
end
353+
346354
test "retrying a job reports error when report: true" do
347355
assert_error_reported(ReportedError) do
348356
RetryJob.perform_later("ReportedError", 2)

activejob/test/jobs/retries_job.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# frozen_string_literal: true
2+
3+
class BeforeEnqueueError < StandardError; end
4+
5+
class RetriesJob < ActiveJob::Base
6+
attr_accessor :raise_before_enqueue
7+
8+
# The job fails in before_enqueue the first time it retries itself.
9+
before_perform do
10+
self.raise_before_enqueue = true
11+
end
12+
13+
# The job fails once to enqueue/retry itself, then succeeds.
14+
before_enqueue do
15+
raise BeforeEnqueueError if raise_before_enqueue
16+
ensure
17+
@raise_before_enqueue = false
18+
end
19+
20+
# The job retries on BeforeEnqueueError errors.
21+
retry_on BeforeEnqueueError
22+
23+
def perform
24+
retry_job if executions <= 1
25+
end
26+
end

0 commit comments

Comments
 (0)