ci-queue 0.12.1 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|