ci-queue 0.65.0 → 0.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/ci/queue/redis/acknowledge.lua +11 -2
- data/lib/ci/queue/redis/base.rb +8 -5
- data/lib/ci/queue/redis/build_record.rb +8 -9
- data/lib/ci/queue/redis/grind_record.rb +1 -1
- data/lib/ci/queue/redis/test_time_record.rb +4 -4
- data/lib/ci/queue/redis/worker.rb +15 -8
- data/lib/ci/queue/redis.rb +1 -0
- data/lib/ci/queue/static.rb +2 -2
- data/lib/ci/queue/version.rb +1 -1
- data/lib/minitest/queue/build_status_recorder.rb +1 -1
- data/lib/minitest/queue.rb +2 -8
- data/lib/rspec/queue.rb +1 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3a701add5867e968b8dcc2c8d9fe301f88b54ede5b0f2f615171fa1d620e6bd
|
4
|
+
data.tar.gz: 401f2f2c45c09edbd609c177a077b1aec2fe361f376439d6f5b8a29770d7e488
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f32ff8fa093d89df2194ac043943de43acfedbc5cbcf942c3638d0cc6ccf9659eb107dbf87ef04b3f19ba8329adf1b1275cb2125b8bc9c3cafd7072b49de3e5c
|
7
|
+
data.tar.gz: 01c75cfae762cb874df2160b04c7b96d14d7665631dfaaf642553587b14f7e86bd4d093aad6b9feefa3bee67b6626c3b2a143f3695f50b942579c59949eb16ed
|
data/Gemfile.lock
CHANGED
@@ -2,9 +2,18 @@
|
|
2
2
|
local zset_key = KEYS[1]
|
3
3
|
local processed_key = KEYS[2]
|
4
4
|
local owners_key = KEYS[3]
|
5
|
+
local error_reports_key = KEYS[4]
|
5
6
|
|
6
7
|
local test = ARGV[1]
|
7
|
-
|
8
|
+
local error = ARGV[2]
|
9
|
+
local ttl = ARGV[3]
|
8
10
|
redis.call('zrem', zset_key, test)
|
9
11
|
redis.call('hdel', owners_key, test) -- Doesn't matter if it was reclaimed by another workers
|
10
|
-
|
12
|
+
local acknowledged = redis.call('sadd', processed_key, test)
|
13
|
+
|
14
|
+
if acknowledged and error ~= "" then
|
15
|
+
redis.call('hset', error_reports_key, test, error)
|
16
|
+
redis.call('expire', error_reports_key, ttl)
|
17
|
+
end
|
18
|
+
|
19
|
+
return acknowledged
|
data/lib/ci/queue/redis/base.rb
CHANGED
@@ -11,6 +11,8 @@ module CI
|
|
11
11
|
::SocketError, # https://github.com/redis/redis-rb/pull/631
|
12
12
|
].freeze
|
13
13
|
|
14
|
+
DEFAULT_TIMEOUT = 2
|
15
|
+
|
14
16
|
module RedisInstrumentation
|
15
17
|
def call(command, redis_config)
|
16
18
|
logger = redis_config.custom[:debug_log]
|
@@ -45,9 +47,10 @@ module CI
|
|
45
47
|
# ci-queue should not contain any sensitive data, so we can just disable the verification.
|
46
48
|
ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE },
|
47
49
|
custom: custom_config,
|
50
|
+
timeout: DEFAULT_TIMEOUT,
|
48
51
|
)
|
49
52
|
else
|
50
|
-
@redis = ::Redis.new(url: redis_url)
|
53
|
+
@redis = ::Redis.new(url: redis_url, timeout: DEFAULT_TIMEOUT)
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
@@ -178,8 +181,8 @@ module CI
|
|
178
181
|
master_status == 'setup'
|
179
182
|
end
|
180
183
|
|
181
|
-
def increment_test_failed
|
182
|
-
|
184
|
+
def increment_test_failed(pipeline: redis)
|
185
|
+
pipeline.incr(key('test_failed_count'))
|
183
186
|
end
|
184
187
|
|
185
188
|
def test_failed
|
@@ -222,8 +225,8 @@ module CI
|
|
222
225
|
redis.get(key('master-status'))
|
223
226
|
end
|
224
227
|
|
225
|
-
def eval_script(script,
|
226
|
-
|
228
|
+
def eval_script(script, keys:, argv:, pipeline: redis)
|
229
|
+
pipeline.evalsha(load_script(script), keys: keys, argv: argv)
|
227
230
|
end
|
228
231
|
|
229
232
|
def load_script(script)
|
@@ -56,23 +56,22 @@ module CI
|
|
56
56
|
redis.rpush(key('warnings'), Marshal.dump([type, attributes]))
|
57
57
|
end
|
58
58
|
|
59
|
+
Test = Struct.new(:id) # Hack
|
60
|
+
|
59
61
|
def record_error(id, payload, stats: nil)
|
60
62
|
redis.pipelined do |pipeline|
|
61
|
-
|
62
|
-
key('error-reports'),
|
63
|
-
id.dup.force_encoding(Encoding::BINARY),
|
64
|
-
payload.dup.force_encoding(Encoding::BINARY),
|
65
|
-
)
|
66
|
-
pipeline.expire(key('error-reports'), config.redis_ttl)
|
63
|
+
@queue.acknowledge(id, error: payload, pipeline: pipeline)
|
67
64
|
record_stats(stats, pipeline: pipeline)
|
65
|
+
@queue.increment_test_failed(pipeline: pipeline)
|
68
66
|
end
|
69
67
|
nil
|
70
68
|
end
|
71
69
|
|
72
|
-
def record_success(id, stats: nil, skip_flaky_record: false)
|
70
|
+
def record_success(id, stats: nil, skip_flaky_record: false, acknowledge: true)
|
71
|
+
@queue.acknowledge(id) if acknowledge
|
73
72
|
error_reports_deleted_count, requeued_count, _ = redis.pipelined do |pipeline|
|
74
|
-
pipeline.hdel(key('error-reports'), id
|
75
|
-
pipeline.hget(key('requeues-count'), id
|
73
|
+
pipeline.hdel(key('error-reports'), id)
|
74
|
+
pipeline.hget(key('requeues-count'), id)
|
76
75
|
record_stats(stats, pipeline: pipeline)
|
77
76
|
end
|
78
77
|
record_flaky(id) if !skip_flaky_record && (error_reports_deleted_count.to_i > 0 || requeued_count.to_i > 0)
|
@@ -22,7 +22,7 @@ module CI
|
|
22
22
|
redis.pipelined do |pipeline|
|
23
23
|
pipeline.lpush(
|
24
24
|
test_time_key(test_name),
|
25
|
-
duration.to_s
|
25
|
+
duration.to_s,
|
26
26
|
)
|
27
27
|
pipeline.expire(test_time_key(test_name), config.redis_ttl)
|
28
28
|
end
|
@@ -33,7 +33,7 @@ module CI
|
|
33
33
|
redis.pipelined do |pipeline|
|
34
34
|
pipeline.lpush(
|
35
35
|
all_test_names_key,
|
36
|
-
test_name
|
36
|
+
test_name,
|
37
37
|
)
|
38
38
|
pipeline.expire(all_test_names_key, config.redis_ttl)
|
39
39
|
end
|
@@ -53,11 +53,11 @@ module CI
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def all_test_names_key
|
56
|
-
"build:#{config.build_id}:list_of_test_names"
|
56
|
+
"build:#{config.build_id}:list_of_test_names"
|
57
57
|
end
|
58
58
|
|
59
59
|
def test_time_key(test_name)
|
60
|
-
"build:#{config.build_id}:#{test_name}"
|
60
|
+
"build:#{config.build_id}:#{test_name}"
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -97,13 +97,13 @@ module CI
|
|
97
97
|
build.report_worker_error(error)
|
98
98
|
end
|
99
99
|
|
100
|
-
def acknowledge(
|
101
|
-
test_key = test.id
|
100
|
+
def acknowledge(test_key, error: nil, pipeline: redis)
|
102
101
|
raise_on_mismatching_test(test_key)
|
103
102
|
eval_script(
|
104
103
|
:acknowledge,
|
105
|
-
keys: [key('running'), key('processed'), key('owners')],
|
106
|
-
argv: [test_key],
|
104
|
+
keys: [key('running'), key('processed'), key('owners'), key('error-reports')],
|
105
|
+
argv: [test_key, error.to_s, config.redis_ttl],
|
106
|
+
pipeline: pipeline,
|
107
107
|
) == 1
|
108
108
|
end
|
109
109
|
|
@@ -146,11 +146,11 @@ module CI
|
|
146
146
|
config.worker_id
|
147
147
|
end
|
148
148
|
|
149
|
-
def raise_on_mismatching_test(
|
150
|
-
if @reserved_test ==
|
149
|
+
def raise_on_mismatching_test(test_key)
|
150
|
+
if @reserved_test == test_key
|
151
151
|
@reserved_test = nil
|
152
152
|
else
|
153
|
-
raise ReservationError, "Acknowledged #{
|
153
|
+
raise ReservationError, "Acknowledged #{test_key.inspect} but #{@reserved_test.inspect} was reserved"
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
@@ -201,7 +201,14 @@ module CI
|
|
201
201
|
def push(tests)
|
202
202
|
@total = tests.size
|
203
203
|
|
204
|
-
|
204
|
+
# We set a unique value (worker_id) and read it back to make "SET if Not eXists" idempotent in case of a retry.
|
205
|
+
value = key('setup', worker_id)
|
206
|
+
_, status = redis.pipelined do |pipeline|
|
207
|
+
pipeline.set(key('master-status'), value, nx: true)
|
208
|
+
pipeline.get(key('master-status'))
|
209
|
+
end
|
210
|
+
|
211
|
+
if @master = (value == status)
|
205
212
|
puts "Worker electected as leader, pushing #{@total} tests to the queue."
|
206
213
|
puts
|
207
214
|
|
data/lib/ci/queue/redis.rb
CHANGED
data/lib/ci/queue/static.rb
CHANGED
@@ -103,12 +103,12 @@ module CI
|
|
103
103
|
@queue.empty?
|
104
104
|
end
|
105
105
|
|
106
|
-
def acknowledge(
|
106
|
+
def acknowledge(...)
|
107
107
|
@progress += 1
|
108
108
|
true
|
109
109
|
end
|
110
110
|
|
111
|
-
def increment_test_failed
|
111
|
+
def increment_test_failed(...)
|
112
112
|
@test_failed = test_failed + 1
|
113
113
|
end
|
114
114
|
|
data/lib/ci/queue/version.rb
CHANGED
@@ -52,7 +52,7 @@ module Minitest
|
|
52
52
|
if (test.failure || test.error?) && !test.skipped?
|
53
53
|
build.record_error("#{test.klass}##{test.name}", dump(test), stats: stats)
|
54
54
|
else
|
55
|
-
build.record_success("#{test.klass}##{test.name}", stats: stats, skip_flaky_record: test.skipped?)
|
55
|
+
build.record_success("#{test.klass}##{test.name}", stats: stats, skip_flaky_record: test.skipped?, acknowledge: !test.requeued?)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
data/lib/minitest/queue.rb
CHANGED
@@ -150,6 +150,7 @@ module Minitest
|
|
150
150
|
end
|
151
151
|
|
152
152
|
class SingleExample
|
153
|
+
attr_reader :method_name
|
153
154
|
|
154
155
|
def initialize(runnable, method_name)
|
155
156
|
@runnable = runnable
|
@@ -250,15 +251,8 @@ module Minitest
|
|
250
251
|
|
251
252
|
if failed && CI::Queue.requeueable?(result) && queue.requeue(example)
|
252
253
|
result.requeue!
|
253
|
-
reporter.record(result)
|
254
|
-
elsif queue.acknowledge(example)
|
255
|
-
reporter.record(result)
|
256
|
-
queue.increment_test_failed if failed
|
257
|
-
elsif !failed
|
258
|
-
# If the test was already acknowledged by another worker (we timed out)
|
259
|
-
# Then we only record it if it is successful.
|
260
|
-
reporter.record(result)
|
261
254
|
end
|
255
|
+
reporter.record(result)
|
262
256
|
end
|
263
257
|
queue.stop_heartbeat!
|
264
258
|
rescue Errno::EPIPE
|
data/lib/rspec/queue.rb
CHANGED
@@ -224,13 +224,8 @@ module RSpec
|
|
224
224
|
reporter.cancel_run!
|
225
225
|
dup.mark_as_requeued!(reporter)
|
226
226
|
return true
|
227
|
-
elsif reporter.acknowledge || !@exception
|
228
|
-
# If the test was already acknowledged by another worker (we timed out)
|
229
|
-
# Then we only record it if it is successful.
|
230
|
-
super(reporter)
|
231
227
|
else
|
232
|
-
reporter
|
233
|
-
return
|
228
|
+
super(reporter)
|
234
229
|
end
|
235
230
|
else
|
236
231
|
super(reporter)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ci-queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.67.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
@@ -254,7 +254,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
254
254
|
- !ruby/object:Gem::Version
|
255
255
|
version: '0'
|
256
256
|
requirements: []
|
257
|
-
rubygems_version: 3.6.
|
257
|
+
rubygems_version: 3.6.9
|
258
258
|
specification_version: 4
|
259
259
|
summary: Distribute tests over many workers using a queue
|
260
260
|
test_files: []
|