ci-queue 0.12.1 → 0.13.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/lib/ci/queue.rb +2 -0
- data/lib/ci/queue/circuit_breaker.rb +36 -0
- data/lib/ci/queue/common.rb +19 -0
- data/lib/ci/queue/configuration.rb +11 -2
- data/lib/ci/queue/redis/base.rb +3 -5
- data/lib/ci/queue/redis/worker.rb +1 -1
- data/lib/ci/queue/static.rb +3 -6
- data/lib/ci/queue/version.rb +1 -1
- data/lib/minitest/queue.rb +10 -0
- data/lib/minitest/queue/runner.rb +9 -0
- data/lib/rspec/queue.rb +23 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d494a80d73d0f5f6d8b478f30b40b8dc2ed90e24031ca6ae96dade3a1995a75e
|
4
|
+
data.tar.gz: 4504d20539f933366c50f96b094cbc0ae3623556d62516b763dd98f5a1c305df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 632de17b6e079142195e34d4b9ac0e3754091f786a430f3e0e82ee282fb4d7b7823c89b8c3ab30c397f228c80b37575420affc34da8f0b1ef5fe23f7e325494c
|
7
|
+
data.tar.gz: 00fa21726fcd0c584af82ffc32fa6a32fc78dbe0672ec2916350890e0c9fa6a00205af9a195e7382c3518183c6d63b9745106b6f1255b5672ab121f34f64f712
|
data/lib/ci/queue.rb
CHANGED
@@ -3,7 +3,9 @@ require 'cgi'
|
|
3
3
|
|
4
4
|
require 'ci/queue/version'
|
5
5
|
require 'ci/queue/output_helpers'
|
6
|
+
require 'ci/queue/circuit_breaker'
|
6
7
|
require 'ci/queue/configuration'
|
8
|
+
require 'ci/queue/common'
|
7
9
|
require 'ci/queue/build_record'
|
8
10
|
require 'ci/queue/static'
|
9
11
|
require 'ci/queue/file'
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module CI
|
2
|
+
module Queue
|
3
|
+
class CircuitBreaker
|
4
|
+
module Disabled
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def report_failure!
|
8
|
+
end
|
9
|
+
|
10
|
+
def report_success!
|
11
|
+
end
|
12
|
+
|
13
|
+
def open?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(max_consecutive_failures:)
|
19
|
+
@max = max_consecutive_failures
|
20
|
+
@consecutive_failures = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def report_failure!
|
24
|
+
@consecutive_failures += 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def report_success!
|
28
|
+
@consecutive_failures = 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def open?
|
32
|
+
@consecutive_failures >= @max
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module CI
|
2
|
+
module Queue
|
3
|
+
module Common
|
4
|
+
attr_reader :config
|
5
|
+
|
6
|
+
def flaky?(test)
|
7
|
+
@config.flaky?(test)
|
8
|
+
end
|
9
|
+
|
10
|
+
def report_failure!
|
11
|
+
config.circuit_breaker.report_failure!
|
12
|
+
end
|
13
|
+
|
14
|
+
def report_success!
|
15
|
+
config.circuit_breaker.report_success!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
|
2
1
|
module CI
|
3
2
|
module Queue
|
4
3
|
class Configuration
|
5
4
|
attr_accessor :timeout, :build_id, :worker_id, :max_requeues
|
6
5
|
attr_accessor :requeue_tolerance, :namespace, :seed, :failing_test, :statsd_endpoint
|
6
|
+
attr_reader :circuit_breaker
|
7
7
|
|
8
8
|
class << self
|
9
9
|
def from_env(env)
|
@@ -26,7 +26,7 @@ module CI
|
|
26
26
|
|
27
27
|
def initialize(
|
28
28
|
timeout: 30, build_id: nil, worker_id: nil, max_requeues: 0, requeue_tolerance: 0,
|
29
|
-
namespace: nil, seed: nil, flaky_tests: [], statsd_endpoint: nil
|
29
|
+
namespace: nil, seed: nil, flaky_tests: [], statsd_endpoint: nil, max_consecutive_failures: nil
|
30
30
|
)
|
31
31
|
@namespace = namespace
|
32
32
|
@timeout = timeout
|
@@ -37,6 +37,15 @@ module CI
|
|
37
37
|
@seed = seed
|
38
38
|
@flaky_tests = flaky_tests
|
39
39
|
@statsd_endpoint = statsd_endpoint
|
40
|
+
self.max_consecutive_failures = max_consecutive_failures
|
41
|
+
end
|
42
|
+
|
43
|
+
def max_consecutive_failures=(max)
|
44
|
+
@circuit_breaker = if max
|
45
|
+
CircuitBreaker.new(max_consecutive_failures: max)
|
46
|
+
else
|
47
|
+
CircuitBreaker::Disabled
|
48
|
+
end
|
40
49
|
end
|
41
50
|
|
42
51
|
def flaky?(test)
|
data/lib/ci/queue/redis/base.rb
CHANGED
@@ -2,16 +2,14 @@ module CI
|
|
2
2
|
module Queue
|
3
3
|
module Redis
|
4
4
|
class Base
|
5
|
+
include Common
|
6
|
+
|
5
7
|
def initialize(redis_url, config)
|
6
8
|
@redis_url = redis_url
|
7
9
|
@redis = ::Redis.new(url: redis_url)
|
8
10
|
@config = config
|
9
11
|
end
|
10
12
|
|
11
|
-
def flaky?(test)
|
12
|
-
@config.flaky?(test)
|
13
|
-
end
|
14
|
-
|
15
13
|
def exhausted?
|
16
14
|
queue_initialized? && size == 0
|
17
15
|
end
|
@@ -59,7 +57,7 @@ module CI
|
|
59
57
|
|
60
58
|
private
|
61
59
|
|
62
|
-
attr_reader :redis, :
|
60
|
+
attr_reader :redis, :redis_url
|
63
61
|
|
64
62
|
def key(*args)
|
65
63
|
['build', build_id, *args].join(':')
|
data/lib/ci/queue/static.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module CI
|
2
2
|
module Queue
|
3
3
|
class Static
|
4
|
+
include Common
|
4
5
|
class << self
|
5
6
|
def from_uri(uri, config)
|
6
7
|
tests = uri.opaque.split(':').map { |t| CGI.unescape(t) }
|
@@ -17,10 +18,6 @@ module CI
|
|
17
18
|
@total = tests.size
|
18
19
|
end
|
19
20
|
|
20
|
-
def flaky?(test)
|
21
|
-
@config.flaky?(test)
|
22
|
-
end
|
23
|
-
|
24
21
|
def build
|
25
22
|
@build ||= BuildRecord.new(self)
|
26
23
|
end
|
@@ -51,7 +48,7 @@ module CI
|
|
51
48
|
end
|
52
49
|
|
53
50
|
def poll
|
54
|
-
while test = @queue.shift
|
51
|
+
while !config.circuit_breaker.open? && test = @queue.shift
|
55
52
|
yield index.fetch(test)
|
56
53
|
@progress += 1
|
57
54
|
end
|
@@ -75,7 +72,7 @@ module CI
|
|
75
72
|
|
76
73
|
private
|
77
74
|
|
78
|
-
attr_reader :index
|
75
|
+
attr_reader :index
|
79
76
|
|
80
77
|
def should_requeue?(key)
|
81
78
|
requeues[key] < config.max_requeues && requeues.values.inject(0, :+) < config.global_max_requeues(total)
|
data/lib/ci/queue/version.rb
CHANGED
data/lib/minitest/queue.rb
CHANGED
@@ -143,6 +143,10 @@ module Minitest
|
|
143
143
|
def __run(*args)
|
144
144
|
if queue
|
145
145
|
run_from_queue(*args)
|
146
|
+
|
147
|
+
if queue.config.circuit_breaker.open?
|
148
|
+
STDERR.puts "This worker is exiting early because it encountered too many consecutive test failures, probably because of some corrupted state."
|
149
|
+
end
|
146
150
|
else
|
147
151
|
super
|
148
152
|
end
|
@@ -158,6 +162,12 @@ module Minitest
|
|
158
162
|
failed = false
|
159
163
|
end
|
160
164
|
|
165
|
+
if failed
|
166
|
+
queue.report_failure!
|
167
|
+
else
|
168
|
+
queue.report_success!
|
169
|
+
end
|
170
|
+
|
161
171
|
if failed && queue.requeue(example)
|
162
172
|
result.requeue!
|
163
173
|
reporter.record(result)
|
@@ -271,6 +271,15 @@ module Minitest
|
|
271
271
|
queue_config.requeue_tolerance = Float(ratio)
|
272
272
|
end
|
273
273
|
|
274
|
+
help = split_heredoc(<<-EOS)
|
275
|
+
Defines after how many consecutive failures the worker will be considered unhealthy and terminate itself.
|
276
|
+
Defaults to disabled.
|
277
|
+
EOS
|
278
|
+
opts.separator ""
|
279
|
+
opts.on('--max-consecutive-failures MAX', *help) do |max|
|
280
|
+
queue_config.max_consecutive_failures = Integer(max)
|
281
|
+
end
|
282
|
+
|
274
283
|
opts.separator ""
|
275
284
|
opts.separator " retry: Replays a previous run in the same order."
|
276
285
|
|
data/lib/rspec/queue.rb
CHANGED
@@ -135,6 +135,15 @@ module RSpec
|
|
135
135
|
queue_config.requeue_tolerance = Float(ratio)
|
136
136
|
end
|
137
137
|
|
138
|
+
help = split_heredoc(<<-EOS)
|
139
|
+
Defines after how many consecutive failures the worker will be considered unhealthy and terminate itself.
|
140
|
+
Defaults to disabled.
|
141
|
+
EOS
|
142
|
+
parser.separator ""
|
143
|
+
parser.on('--max-consecutive-failures MAX', *help) do |max|
|
144
|
+
queue_config.max_consecutive_failures = Integer(max)
|
145
|
+
end
|
146
|
+
|
138
147
|
parser
|
139
148
|
end
|
140
149
|
|
@@ -187,6 +196,12 @@ module RSpec
|
|
187
196
|
|
188
197
|
def finish(reporter, acknowledge: true)
|
189
198
|
if acknowledge && reporter.respond_to?(:requeue)
|
199
|
+
if @exception
|
200
|
+
reporter.report_failure!
|
201
|
+
else
|
202
|
+
reporter.report_success!
|
203
|
+
end
|
204
|
+
|
190
205
|
if @exception && reporter.requeue
|
191
206
|
reporter.cancel_run!
|
192
207
|
dup.mark_as_requeued!(reporter)
|
@@ -301,6 +316,14 @@ module RSpec
|
|
301
316
|
super(reporter)
|
302
317
|
end
|
303
318
|
|
319
|
+
def report_success!
|
320
|
+
@queue.report_success!
|
321
|
+
end
|
322
|
+
|
323
|
+
def report_failure!
|
324
|
+
@queue.report_failure!
|
325
|
+
end
|
326
|
+
|
304
327
|
def requeue
|
305
328
|
@queue.requeue(@example)
|
306
329
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ci-queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ansi
|
@@ -174,6 +174,8 @@ files:
|
|
174
174
|
- lib/ci/queue.rb
|
175
175
|
- lib/ci/queue/bisect.rb
|
176
176
|
- lib/ci/queue/build_record.rb
|
177
|
+
- lib/ci/queue/circuit_breaker.rb
|
178
|
+
- lib/ci/queue/common.rb
|
177
179
|
- lib/ci/queue/configuration.rb
|
178
180
|
- lib/ci/queue/file.rb
|
179
181
|
- lib/ci/queue/output_helpers.rb
|