Skip to content

Commit cf5eafa

Browse files
committed
Avoid repeated calls to respond_to?
The common case is that the class will implement `succ`, so catch NoMethodError's instead to avoid the repeated calls to `respond_to?`. Also add test coverage for advancing cursors.
1 parent 50f2341 commit cf5eafa

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

activejob/lib/active_job/continuation/step.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,14 @@ def set!(cursor)
4848
# An UnadvanceableCursorError error will be raised if the cursor does not implement +succ+.
4949
def advance!(from: nil)
5050
from = cursor if from.nil?
51-
raise UnadvanceableCursorError, "Cursor class '#{from.class}' does not implement succ, " unless from.respond_to?(:succ)
52-
set! from.succ
51+
52+
begin
53+
to = from.succ
54+
rescue NoMethodError
55+
raise UnadvanceableCursorError, "Cursor class '#{from.class}' does not implement 'succ'"
56+
end
57+
58+
set! to
5359
end
5460

5561
# Has this step been resumed from a previous job execution?

activejob/test/cases/continuation_test.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818

1919
return unless adapter_is?(:test)
2020

21+
class ContinuableJob < ActiveJob::Base
22+
include ActiveJob::Continuable
23+
end
24+
2125
class ActiveJob::TestContinuation < ActiveSupport::TestCase
2226
include ActiveJob::Continuation::TestHelper
2327
include ActiveSupport::Testing::Stream
@@ -251,6 +255,38 @@ class ActiveJob::TestContinuation < ActiveSupport::TestCase
251255
assert_equal "Step 'unexpected' found, expected to resume from 'iterating'", exception.message
252256
end
253257

258+
class ContinuableAdvancingJob < ContinuableJob
259+
def perform(start_from, advance_from = nil)
260+
step :test_step, start: start_from do |step|
261+
step.advance! from: advance_from
262+
end
263+
end
264+
end
265+
266+
test "cursor must implement succ to advance" do
267+
perform_enqueued_jobs do
268+
assert_raises ActiveJob::Continuation::UnadvanceableCursorError do
269+
ContinuableAdvancingJob.perform_later(nil)
270+
end
271+
272+
assert_raises ActiveJob::Continuation::UnadvanceableCursorError do
273+
ContinuableAdvancingJob.perform_later(1.1)
274+
end
275+
276+
assert_raises ActiveJob::Continuation::UnadvanceableCursorError do
277+
ContinuableAdvancingJob.perform_later(nil, 1.1)
278+
end
279+
280+
assert_nothing_raised do
281+
ContinuableAdvancingJob.perform_later(1)
282+
end
283+
284+
assert_nothing_raised do
285+
ContinuableAdvancingJob.perform_later(nil, 1)
286+
end
287+
end
288+
end
289+
254290
test "deserializes a job with no continuation" do
255291
ContinuableDeletingJob.items = 10.times.map { |i| "item_#{i}" }
256292
ContinuableDeletingJob.perform_later

0 commit comments

Comments
 (0)