From a01c8676ab980e57f3bb4671556ef675ab713239 Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Fri, 23 May 2025 13:45:30 +0900 Subject: [PATCH 1/3] Allow reserving multiple tests --- ruby/lib/ci/queue/redis/worker.rb | 25 ++++++++++++------------- ruby/lib/ci/queue/static.rb | 13 +++++++++---- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/ruby/lib/ci/queue/redis/worker.rb b/ruby/lib/ci/queue/redis/worker.rb index 3fbf2f9b..db87e566 100644 --- a/ruby/lib/ci/queue/redis/worker.rb +++ b/ruby/lib/ci/queue/redis/worker.rb @@ -16,7 +16,7 @@ class Worker < Base attr_reader :total def initialize(redis, config) - @reserved_test = nil + @reserved_tests = Set.new @shutdown_required = false super(redis, config) end @@ -135,7 +135,7 @@ def requeue(test, offset: Redis.requeue_offset) argv: [config.max_requeues, global_max_requeues, test_key, offset], ) == 1 - @reserved_test = test_key unless requeued + reserved_tests << test_key unless requeued requeued end @@ -152,25 +152,24 @@ def release! attr_reader :index + def reserved_tests + @reserved_tests ||= Set.new + end + def worker_id config.worker_id end - def raise_on_mismatching_test(test_key) - if @reserved_test == test_key - @reserved_test = nil - else - raise ReservationError, "Acknowledged #{test_key.inspect} but #{@reserved_test.inspect} was reserved" + def raise_on_mismatching_test(test) + unless reserved_tests.delete?(test) + raise ReservationError, "Acknowledged #{test.inspect} but only #{reserved_tests.map(&:inspect).join(", ")} reserved" end end def reserve - if @reserved_test - raise ReservationError, "#{@reserved_test.inspect} is already reserved. " \ - "You have to acknowledge it before you can reserve another one" - end - - @reserved_test = (try_to_reserve_lost_test || try_to_reserve_test) + test = (try_to_reserve_lost_test || try_to_reserve_test) + reserved_tests << test + test end def try_to_reserve_test diff --git a/ruby/lib/ci/queue/static.rb b/ruby/lib/ci/queue/static.rb index d6a2a28b..c70f3077 100644 --- a/ruby/lib/ci/queue/static.rb +++ b/ruby/lib/ci/queue/static.rb @@ -89,14 +89,15 @@ def remaining end def running - @reserved_test ? 1 : 0 + reserved_tests.empty? ? 0 : 1 end def poll - while !@shutdown && config.circuit_breakers.none?(&:open?) && !max_test_failed? && @reserved_test = @queue.shift - yield index.fetch(@reserved_test) + while !@shutdown && config.circuit_breakers.none?(&:open?) && !max_test_failed? && reserved_test = @queue.shift + reserved_tests << reserved_test + yield index.fetch(reserved_test) end - @reserved_test = nil + @reserved_tests.clear end def exhausted? @@ -142,6 +143,10 @@ def should_requeue?(key) def requeues @requeues ||= Hash.new(0) end + + def reserved_tests + @reserved_tests ||= Set.new + end end end end From 3035c5f39fc8e74122fbf50a04467d8b4e3462b0 Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Fri, 23 May 2025 16:01:59 +0900 Subject: [PATCH 2/3] Use reserved_tests reader --- ruby/lib/ci/queue/static.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/lib/ci/queue/static.rb b/ruby/lib/ci/queue/static.rb index c70f3077..1e725288 100644 --- a/ruby/lib/ci/queue/static.rb +++ b/ruby/lib/ci/queue/static.rb @@ -97,7 +97,7 @@ def poll reserved_tests << reserved_test yield index.fetch(reserved_test) end - @reserved_tests.clear + reserved_tests.clear end def exhausted? From aaf2f7e5ea65a4003b20b3b71b26135d7378eccf Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Wed, 18 Jun 2025 10:44:39 +0900 Subject: [PATCH 3/3] Update test to use reserved_tests --- ruby/test/minitest/queue/build_status_recorder_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/test/minitest/queue/build_status_recorder_test.rb b/ruby/test/minitest/queue/build_status_recorder_test.rb index 35b4efcd..babfb8c3 100644 --- a/ruby/test/minitest/queue/build_status_recorder_test.rb +++ b/ruby/test/minitest/queue/build_status_recorder_test.rb @@ -79,7 +79,7 @@ def test_retrying_test private def reserve(queue, method_name) - queue.instance_variable_set(:@reserved_test, Minitest::Queue::SingleExample.new("Minitest::Test", method_name).id) + queue.instance_variable_set(:@reserved_tests, Set.new([Minitest::Queue::SingleExample.new("Minitest::Test", method_name).id])) end def worker(id)