From 81d59757207505499d69f67336c027d0432bb8ca Mon Sep 17 00:00:00 2001 From: wintan1418 Date: Thu, 30 Jul 2026 13:23:39 +0100 Subject: [PATCH] Keep semaphore slots held while blocked jobs are enqueued in concurrency test "run several jobs over the same record limiting concurrency" claims all three semaphore slots with jobs A, B and C, then enqueues D-H expecting all five to block. A and B only paused for 0.5 seconds, so on a slow CI runner they could finish while D-H were still being inserted, freeing a slot that let some of them run instead of blocking and failing the +5 BlockedExecution assertion. Give A and B enough pause to outlive the enqueue window, and bump C accordingly so it still saves last. Related to rails/solid_queue#602 --- test/integration/concurrency_controls_test.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/integration/concurrency_controls_test.rb b/test/integration/concurrency_controls_test.rb index 9cdb3d65..e4d40100 100644 --- a/test/integration/concurrency_controls_test.rb +++ b/test/integration/concurrency_controls_test.rb @@ -75,10 +75,13 @@ class ConcurrencyControlsTest < ActiveSupport::TestCase # and B finish quickly, freeing slots that drain D–H; C reads the empty # status and pauses far longer than everyone else, so it saves last and its # write (built on the empty status) overwrites all the others, leaving "C". + # A and B must pause long enough to still hold their semaphore slots while + # D–H are being enqueued, even on a slow CI runner — otherwise some of D–H + # claim a freed slot instead of blocking. assert_no_difference -> { SolidQueue::BlockedExecution.count } do - ThrottledUpdateResultJob.perform_later(@result, name: "A", pause: 0.5.seconds) - ThrottledUpdateResultJob.perform_later(@result, name: "B", pause: 0.5.seconds) - ThrottledUpdateResultJob.perform_later(@result, name: "C", pause: 3.seconds) + ThrottledUpdateResultJob.perform_later(@result, name: "A", pause: 1.5.seconds) + ThrottledUpdateResultJob.perform_later(@result, name: "B", pause: 1.5.seconds) + ThrottledUpdateResultJob.perform_later(@result, name: "C", pause: 4.seconds) end wait_for(timeout: 2.seconds) { SolidQueue::ClaimedExecution.count >= 3 }