Skip to content

Commit ddfe719

Browse files
committed
Clean up tests after unifying discard behaviour
1 parent bd2b655 commit ddfe719

File tree

7 files changed

+124
-318
lines changed

7 files changed

+124
-318
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ class MyJob < ApplicationJob
442442
- `group` is used to control the concurrency of different job classes together. It defaults to the job class name.
443443
- `on_conflict` controls behaviour when enqueuing a job that conflicts with the concurrency limits configured. It can be set to one of the following:
444444
- (default) `:block`: the job is blocked and is dispatched when another job completes and unblocks it, or when the duration expires.
445-
- `:discard`: the job is discarded (silently finishes). When you choose this option, bear in mind that if a job runs and fails to remove the concurrency lock (or _semaphore_, read below to know more about this), all jobs conflicting with it will be discarded up to the interval defined by `duration` has elapsed.
445+
- `:discard`: the job is discarded (silently finishes). When you choose this option, bear in mind that if a job runs and fails to remove the concurrency lock (or _semaphore_, read below to know more about this), all jobs conflicting with it will be discarded up to the interval defined by `duration` has elapsed. Additionally, Active Jobs that are discarded will have `successfully_enqueued` set to `false`.
446446

447447
When a job includes these controls, we'll ensure that, at most, the number of jobs (indicated as `to`) that yield the same `key` will be performed concurrently, and this guarantee will last for `duration` for each job enqueued. Note that there's no guarantee about _the order of execution_, only about jobs being performed at the same time (overlapping).
448448

test/dummy/app/jobs/discard_on_conflict_job.rb

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class DiscardableUpdateResultJob < UpdateResultJob
2+
limits_concurrency key: ->(job_result, **) { job_result }, on_conflict: :discard
3+
end

test/dummy/app/jobs/limited_discard_job.rb

Lines changed: 0 additions & 8 deletions
This file was deleted.

test/integration/concurrency_controls_test.rb

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,61 @@ class ConcurrencyControlsTest < ActiveSupport::TestCase
196196
end
197197
end
198198

199+
test "discard jobs when concurrency limit is reached with on_conflict: :discard" do
200+
# Enqueue first job - should be executed
201+
job1 = DiscardableUpdateResultJob.perform_later(@result, name: "1", pause: 0.2)
202+
# Enqueue second job - should be discarded due to concurrency limit
203+
job2 = DiscardableUpdateResultJob.perform_later(@result, name: "2")
204+
# Enqueue third job - should also be discarded
205+
job3 = DiscardableUpdateResultJob.perform_later(@result, name: "3")
206+
207+
wait_for_jobs_to_finish_for(5.seconds)
208+
assert_no_unfinished_jobs
209+
210+
# Only the first job did something
211+
assert_stored_sequence(@result, [ "1" ])
212+
213+
# All jobs have finished and have no blocked executions
214+
jobs = SolidQueue::Job.where(active_job_id: [ job1, job2, job3 ].map(&:job_id))
215+
assert_equal 3, jobs.count
216+
217+
jobs.each do |job|
218+
assert job.finished?
219+
assert_nil job.blocked_execution
220+
end
221+
end
222+
223+
test "discard on conflict across different concurrency keys" do
224+
another_result = JobResult.create!(queue_name: "default", status: "seq: ")
225+
DiscardableUpdateResultJob.perform_later(@result, name: "1", pause: 0.2)
226+
DiscardableUpdateResultJob.perform_later(another_result, name: "2", pause: 0.2)
227+
DiscardableUpdateResultJob.perform_later(@result, name: "3") # Should be discarded
228+
DiscardableUpdateResultJob.perform_later(another_result, name: "4") # Should be discarded
229+
230+
wait_for_jobs_to_finish_for(5.seconds)
231+
assert_no_unfinished_jobs
232+
233+
# Only the first 2 jobs did something
234+
assert_stored_sequence(@result, [ "1" ])
235+
assert_stored_sequence(another_result, [ "2" ])
236+
end
237+
238+
test "discard on conflict and release semaphore" do
239+
DiscardableUpdateResultJob.perform_later(@result, name: "1", pause: 0.1)
240+
# will be discarded
241+
DiscardableUpdateResultJob.perform_later(@result, name: "2")
242+
243+
wait_for_jobs_to_finish_for(5.seconds)
244+
assert_no_unfinished_jobs
245+
246+
# Enqueue another job that shouldn't be discarded or blocked
247+
DiscardableUpdateResultJob.perform_later(@result, name: "3")
248+
wait_for_jobs_to_finish_for(5.seconds)
249+
assert_no_unfinished_jobs
250+
251+
assert_stored_sequence(@result, [ "1", "3" ])
252+
end
253+
199254
private
200255
def assert_stored_sequence(result, *sequences)
201256
expected = sequences.map { |sequence| "seq: " + sequence.map { |name| "s#{name}c#{name}" }.join }

test/integration/concurrency_discard_test.rb

Lines changed: 0 additions & 137 deletions
This file was deleted.

0 commit comments

Comments
 (0)