Skip to content

Commit dd0905d

Browse files
committed
Refactor: move record_stats out of record_error/success/requeue
- BuildStatusRecorder: record outcome first, then call build.record_stats(stats) only when acknowledged; combine into single if acknowledged block - Redis BuildRecord: record_error/record_success/record_requeue no longer take stats; add public record_stats(stats, pipeline: nil) - In-memory BuildRecord: same API change; record_stats public - GrindRecord/GrindRecorder: same pattern - record_error/record_success without stats, record_stats at end - Tests: update callers to use new API (no stats in record_*; record_stats called separately where needed)
1 parent 2774897 commit dd0905d

7 files changed

Lines changed: 62 additions & 66 deletions

File tree

ruby/lib/ci/queue/build_record.rb

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,25 @@ def queue_exhausted?
1818
@queue.exhausted?
1919
end
2020

21-
def record_error(id, payload, stats: nil)
21+
def record_error(id, payload)
2222
error_reports[id] = payload
23-
record_stats(stats)
2423
true
2524
end
2625

27-
def record_success(id, stats: nil, skip_flaky_record: false, acknowledge: true)
26+
def record_success(id, skip_flaky_record: false, acknowledge: true)
2827
error_reports.delete(id)
29-
record_stats(stats)
3028
true
3129
end
3230

33-
def record_requeue(id, stats: nil)
31+
def record_requeue(id)
3432
true
3533
end
3634

35+
def record_stats(builds_stats)
36+
return unless builds_stats
37+
stats.merge!(builds_stats)
38+
end
39+
3740
def fetch_stats(stat_names)
3841
stat_names.zip(stats.values_at(*stat_names).map(&:to_f))
3942
end
@@ -53,11 +56,6 @@ def worker_errors
5356
private
5457

5558
attr_reader :stats
56-
57-
def record_stats(builds_stats)
58-
return unless builds_stats
59-
stats.merge!(builds_stats)
60-
end
6159
end
6260
end
6361
end

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

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,39 +56,46 @@ def record_warning(type, attributes)
5656
redis.rpush(key('warnings'), Marshal.dump([type, attributes]))
5757
end
5858

59-
def record_error(id, payload, stats: nil)
59+
def record_error(id, payload)
6060
# Run acknowledge first so we know whether we're the first to ack
6161
acknowledged = @queue.acknowledge(id, error: payload)
6262

6363
if acknowledged
6464
# We were the first to ack; another worker already ack'd would get falsy from SADD
65-
redis.pipelined do |pipeline|
66-
record_stats(stats, pipeline: pipeline)
67-
end
6865
@queue.increment_test_failed
6966
end
7067
# Return so caller can roll back local counter when not acknowledged
7168
!!acknowledged
7269
end
7370

74-
def record_success(id, stats: nil, skip_flaky_record: false)
75-
acknowledged, error_reports_deleted_count, requeued_count, _ = redis.multi do |transaction|
71+
def record_success(id, skip_flaky_record: false)
72+
acknowledged, error_reports_deleted_count, requeued_count = redis.multi do |transaction|
7673
@queue.acknowledge(id, pipeline: transaction)
7774
transaction.hdel(key('error-reports'), id)
7875
transaction.hget(key('requeues-count'), id)
79-
record_stats(stats, pipeline: transaction)
8076
end
8177
record_flaky(id) if !skip_flaky_record && (error_reports_deleted_count.to_i > 0 || requeued_count.to_i > 0)
8278
!!acknowledged
8379
end
8480

85-
def record_requeue(id, stats: nil)
86-
redis.pipelined do |pipeline|
87-
record_stats(stats, pipeline: pipeline)
88-
end
81+
def record_requeue(id)
8982
true
9083
end
9184

85+
def record_stats(stats, pipeline: nil)
86+
return unless stats
87+
if pipeline
88+
stats.each do |stat_name, stat_value|
89+
pipeline.hset(key(stat_name), config.worker_id, stat_value)
90+
pipeline.expire(key(stat_name), config.redis_ttl)
91+
end
92+
else
93+
redis.pipelined do |p|
94+
record_stats(stats, pipeline: p)
95+
end
96+
end
97+
end
98+
9299
def record_flaky(id, stats: nil)
93100
redis.pipelined do |pipeline|
94101
pipeline.sadd?(
@@ -136,14 +143,6 @@ def reset_stats(stat_names)
136143

137144
attr_reader :config, :redis
138145

139-
def record_stats(stats, pipeline: redis)
140-
return unless stats
141-
stats.each do |stat_name, stat_value|
142-
pipeline.hset(key(stat_name), config.worker_id, stat_value)
143-
pipeline.expire(key(stat_name), config.redis_ttl)
144-
end
145-
end
146-
147146
def key(*args)
148147
KeyShortener.key(config.build_id, *args)
149148
end

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

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,32 @@ def initialize(queue, redis, config)
1010
@config = config
1111
end
1212

13-
def record_error(payload, stats: nil)
13+
def record_error(payload)
1414
redis.pipelined do |pipeline|
1515
pipeline.lpush(
1616
key('error-reports'),
1717
payload,
1818
)
1919
pipeline.expire(key('error-reports'), config.redis_ttl)
20-
record_stats(stats, pipeline: pipeline)
2120
end
2221
nil
2322
end
2423

25-
def record_success(stats: nil)
26-
record_stats(stats)
24+
def record_success
25+
end
26+
27+
def record_stats(stats, pipeline: nil)
28+
return unless stats
29+
if pipeline
30+
stats.each do |stat_name, stat_value|
31+
pipeline.hset(key(stat_name), config.worker_id, stat_value)
32+
pipeline.expire(key(stat_name), config.redis_ttl)
33+
end
34+
else
35+
redis.pipelined do |p|
36+
record_stats(stats, pipeline: p)
37+
end
38+
end
2739
end
2840

2941
def record_warning(_,_)
@@ -54,14 +66,6 @@ def pop_warnings
5466
def key(*args)
5567
KeyShortener.key(config.build_id, *args)
5668
end
57-
58-
def record_stats(stats, pipeline: redis)
59-
return unless stats
60-
stats.each do |stat_name, stat_value|
61-
pipeline.hset(key(stat_name), config.worker_id, stat_value)
62-
pipeline.expire(key(stat_name), config.redis_ttl)
63-
end
64-
end
6569
end
6670
end
6771
end

ruby/lib/minitest/queue/build_status_recorder.rb

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,16 @@ def record(test)
3838
super
3939

4040
self.total_time = Minitest.clock_time - start_time
41-
stats = COUNTERS.zip(COUNTERS.map { |c| send(c) + stat_delta(c, test) }).to_h
41+
42+
# Determine what type of result this is and record it
43+
test_id = "#{test.klass}##{test.name}"
4244

4345
acknowledged = if (test.failure || test.error?) && !test.skipped?
44-
build.record_error("#{test.klass}##{test.name}", dump(test), stats: stats)
46+
build.record_error(test_id, dump(test))
4547
elsif test.requeued?
46-
build.record_requeue("#{test.klass}##{test.name}", stats: stats)
48+
build.record_requeue(test_id)
4749
else
48-
build.record_success("#{test.klass}##{test.name}", stats: stats, skip_flaky_record: test.skipped?)
50+
build.record_success(test_id, skip_flaky_record: test.skipped?)
4951
end
5052

5153
if acknowledged
@@ -56,21 +58,13 @@ def record(test)
5658
elsif test.skipped?
5759
self.skips += 1
5860
end
61+
stats = COUNTERS.zip(COUNTERS.map { |c| send(c) }).to_h
62+
build.record_stats(stats)
5963
end
6064
end
6165

6266
private
6367

64-
def stat_delta(counter, test)
65-
case counter
66-
when 'errors' then test.error? && !test.skipped? ? 1 : 0
67-
when 'failures' then test.failure && !test.skipped? ? 1 : 0
68-
when 'skips' then test.skipped? ? 1 : 0
69-
when 'requeues' then test.requeued? ? 1 : 0
70-
else 0
71-
end
72-
end
73-
7468
def dump(test)
7569
ErrorReport.new(self.class.failure_formatter.new(test).to_h).dump
7670
end

ruby/lib/minitest/queue/grind_recorder.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ def record(test)
3232
private
3333

3434
def record_test(test)
35-
stats = self.class.counters
3635
if (test.failure || test.error?) && !test.skipped?
37-
build.record_error(dump(test), stats: stats)
36+
build.record_error(dump(test))
3837
else
39-
build.record_success(stats: stats)
38+
build.record_success
4039
end
40+
build.record_stats(self.class.counters)
4141
end
4242

4343
def increment_counter(test)

ruby/test/integration/minitest_redis_test.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,14 +513,15 @@ def test_retry_report
513513

514514
error_reports.keys.each_with_index do |test_id, index|
515515
queue.instance_variable_set(:@reserved_tests, Concurrent::Set.new([test_id]))
516-
queue.build.record_success(test_id.dup, stats: {
516+
queue.build.record_success(test_id.dup)
517+
queue.build.record_stats(
517518
'assertions' => index + 1,
518519
'errors' => 0,
519520
'failures' => 0,
520521
'skips' => 0,
521522
'requeues' => 0,
522523
'total_time' => index + 1,
523-
})
524+
)
524525
end
525526

526527
# Retry first worker, bailing out

ruby/test/minitest/queue/build_status_recorder_test.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,21 +145,21 @@ def test_duplicate_success_does_not_increment_skips
145145
def test_build_record_methods_return_boolean
146146
# Redis build: first to ack returns true, duplicate returns false
147147
reserve(@queue, "a")
148-
assert_equal true, @queue.build.record_success("Minitest::Test#a", stats: { 'assertions' => 1, 'errors' => 0, 'failures' => 0, 'skips' => 0, 'requeues' => 0, 'total_time' => 0.1 })
149-
assert_equal true, @queue.build.record_requeue("Minitest::Test#b", stats: { 'assertions' => 1, 'errors' => 0, 'failures' => 0, 'skips' => 0, 'requeues' => 1, 'total_time' => 0.1 })
148+
assert_equal true, @queue.build.record_success("Minitest::Test#a")
149+
assert_equal true, @queue.build.record_requeue("Minitest::Test#b")
150150

151151
second_queue = worker(2)
152152
reserve(second_queue, "a")
153-
assert_equal false, second_queue.build.record_success("Minitest::Test#a", stats: { 'assertions' => 1, 'errors' => 0, 'failures' => 0, 'skips' => 0, 'requeues' => 0, 'total_time' => 0.1 })
153+
assert_equal false, second_queue.build.record_success("Minitest::Test#a")
154154
end
155155

156156
def test_static_build_record_returns_true
157157
static_queue = CI::Queue::Static.new(['test_example'], CI::Queue::Configuration.new(build_id: '42', worker_id: '1'))
158158
build = static_queue.build
159159

160-
assert_equal true, build.record_success("test_example", stats: { 'assertions' => 0, 'errors' => 0, 'failures' => 0, 'skips' => 0, 'requeues' => 0, 'total_time' => 0 })
161-
assert_equal true, build.record_requeue("test_example", stats: { 'assertions' => 0, 'errors' => 0, 'failures' => 0, 'skips' => 0, 'requeues' => 1, 'total_time' => 0 })
162-
assert_equal true, build.record_error("test_example", "payload", stats: {})
160+
assert_equal true, build.record_success("test_example")
161+
assert_equal true, build.record_requeue("test_example")
162+
assert_equal true, build.record_error("test_example", "payload")
163163
end
164164

165165
private

0 commit comments

Comments
 (0)