Skip to content

Commit 57648bc

Browse files
committed
batch submitting chunks to redis
1 parent ee83285 commit 57648bc

File tree

2 files changed

+46
-12
lines changed

2 files changed

+46
-12
lines changed

ruby/lib/ci/queue/redis/worker.rb

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -276,19 +276,25 @@ def register
276276
private
277277

278278
def store_chunk_metadata(chunks)
279-
redis.multi do |transaction|
280-
chunks.each do |chunk|
281-
# Store chunk metadata with TTL
282-
transaction.set(
283-
key('chunk', chunk.id),
284-
chunk.to_json
285-
)
286-
transaction.expire(key('chunk', chunk.id), config.redis_ttl)
287-
288-
# Track all chunks for cleanup
289-
transaction.sadd(key('chunks'), chunk.id)
279+
# Batch operations to avoid exceeding Redis multi operation limits
280+
# Each chunk requires 3 commands (set, expire, sadd), so batch conservatively
281+
batch_size = 7 # 7 chunks = 21 commands + 1 expire = 22 commands per batch
282+
283+
chunks.each_slice(batch_size) do |chunk_batch|
284+
redis.multi do |transaction|
285+
chunk_batch.each do |chunk|
286+
# Store chunk metadata with TTL
287+
transaction.set(
288+
key('chunk', chunk.id),
289+
chunk.to_json
290+
)
291+
transaction.expire(key('chunk', chunk.id), config.redis_ttl)
292+
293+
# Track all chunks for cleanup
294+
transaction.sadd(key('chunks'), chunk.id)
295+
end
296+
transaction.expire(key('chunks'), config.redis_ttl)
290297
end
291-
transaction.expire(key('chunks'), config.redis_ttl)
292298
end
293299
end
294300

ruby/test/ci/queue/redis/worker_chunk_test.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,34 @@ def test_chunk_metadata_has_ttl
202202
assert ttl > 0, 'Chunk metadata should have TTL set'
203203
end
204204

205+
def test_populate_with_many_chunks_uses_batching
206+
# Create 20 test chunks to verify batching works (batch size is 7)
207+
tests = (1..20).map { |i| MockTest.new("TestSuite#{i}#test_1") }
208+
chunks = (1..20).map do |i|
209+
CI::Queue::TestChunk.new("TestSuite#{i}:full_suite", "TestSuite#{i}", :full_suite, [], 1000.0)
210+
end
211+
212+
CI::Queue.stub(:shuffle, chunks) do
213+
@worker.populate(tests)
214+
end
215+
216+
# Verify all chunks were stored despite batching
217+
chunks.each do |chunk|
218+
chunk_data = @redis.get("build:42:chunk:#{chunk.id}")
219+
refute_nil chunk_data, "Chunk #{chunk.id} should be stored"
220+
221+
parsed = JSON.parse(chunk_data)
222+
assert_equal 'full_suite', parsed['type']
223+
assert_equal chunk.suite_name, parsed['suite_name']
224+
end
225+
226+
# Verify all chunk IDs are in the chunks set
227+
stored_chunks = @redis.smembers('build:42:chunks')
228+
chunks.each do |chunk|
229+
assert_includes stored_chunks, chunk.id
230+
end
231+
end
232+
205233
private
206234

207235
def create_mock_tests(test_ids)

0 commit comments

Comments
 (0)