Skip to content

Commit 1dc4b25

Browse files
author
Doug Edey
committed
Add support for a custom TTL of Redis keys, defaulting to 8 hours
1 parent b006aaf commit 1dc4b25

File tree

9 files changed

+44
-2
lines changed

9 files changed

+44
-2
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ Two implementations are provided, please refer to the respective documentations:
3737
- [Python](python/)
3838
- [Ruby](ruby/)
3939

40+
## Redis Requirements
41+
42+
`ci-queue` expects the Redis server to have an [eviction policy](https://redis.io/docs/manual/eviction/#eviction-policies) of `allkeys-lru`.
4043
## Contributing
4144

4245
Bug reports and pull requests are welcome on GitHub at https://github.com/Shopify/ci-queue.

ruby/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,9 @@ rspec-queue --queue redis://example.com --timeout 600 --report
7070
#### Limitations
7171

7272
Because of how `ci-queue` executes the examples, `before(:all)` and `after(:all)` hooks are not supported. `rspec-queue` will explicitly reject them.
73+
74+
## Custom Redis Expiry
75+
76+
`ci-queue` expects the Redis server to have an [eviction policy](https://redis.io/docs/manual/eviction/#eviction-policies) of `allkeys-lru`.
77+
78+
You can also use `--report-expires-in` to set a custom expiration time for all CI Queue keys, this defaults to 8 hours (28,800 seconds)

ruby/lib/ci/queue/configuration.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class Configuration
55
attr_accessor :timeout, :worker_id, :max_requeues, :grind_count, :failure_file
66
attr_accessor :requeue_tolerance, :namespace, :failing_test, :statsd_endpoint
77
attr_accessor :max_test_duration, :max_test_duration_percentile, :track_test_duration
8-
attr_accessor :max_test_failed
8+
attr_accessor :max_test_failed, :report_expires_in
99
attr_reader :circuit_breakers
1010
attr_writer :seed, :build_id
1111
attr_writer :queue_init_timeout
@@ -34,7 +34,7 @@ def initialize(
3434
namespace: nil, seed: nil, flaky_tests: [], statsd_endpoint: nil, max_consecutive_failures: nil,
3535
grind_count: nil, max_duration: nil, failure_file: nil, max_test_duration: nil,
3636
max_test_duration_percentile: 0.5, track_test_duration: false, max_test_failed: nil,
37-
queue_init_timeout: nil
37+
queue_init_timeout: nil, report_expires_in: 8 * 60 * 60
3838
)
3939
@build_id = build_id
4040
@circuit_breakers = [CircuitBreaker::Disabled]
@@ -55,6 +55,7 @@ def initialize(
5555
@worker_id = worker_id
5656
self.max_consecutive_failures = max_consecutive_failures
5757
self.max_duration = max_duration
58+
@report_expires_in = report_expires_in
5859
end
5960

6061
def queue_init_timeout

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def record_error(id, payload, stats: nil)
4141
id.dup.force_encoding(Encoding::BINARY),
4242
payload.dup.force_encoding(Encoding::BINARY),
4343
)
44+
pipeline.expire(key('error-reports'), config.report_expires_in)
4445
record_stats(stats, pipeline: pipeline)
4546
end
4647
nil
@@ -90,6 +91,7 @@ def record_stats(stats, pipeline: redis)
9091
return unless stats
9192
stats.each do |stat_name, stat_value|
9293
pipeline.hset(key(stat_name), config.worker_id, stat_value)
94+
pipeline.expire(key(stat-name), config.report_expires_in)
9395
end
9496
end
9597

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ def record_error(payload, stats: nil)
1616
key('error-reports'),
1717
payload.force_encoding(Encoding::BINARY),
1818
)
19+
pipeline.expire(key('error-reports'), config.report_expires_in)
1920
record_stats(stats, pipeline: pipeline)
2021
end
2122
nil
@@ -58,6 +59,7 @@ def record_stats(stats, pipeline: redis)
5859
return unless stats
5960
stats.each do |stat_name, stat_value|
6061
pipeline.hset(key(stat_name), config.worker_id, stat_value)
62+
pipeline.expire(key(stat_name), config.report_expires_in)
6163
end
6264
end
6365
end

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def record_test_time(test_name, duration)
2424
test_time_key(test_name),
2525
duration.to_s.force_encoding(Encoding::BINARY),
2626
)
27+
pipeline.expire(test_time_key(test_name), config.report_expires_in)
2728
end
2829
nil
2930
end
@@ -34,6 +35,7 @@ def record_test_name(test_name)
3435
all_test_names_key,
3536
test_name.dup.force_encoding(Encoding::BINARY),
3637
)
38+
pipeline.expire(all_test_names_key, config.report_expires_in)
3739
end
3840
nil
3941
end

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ def poll
5353
sleep 0.05
5454
end
5555
end
56+
redis.pipelined do |pipeline|
57+
pipeline.expire(key('worker', worker_id, 'queue'), config.report_expires_in)
58+
pipeline.expire(key('processed'), config.report_expires_in)
59+
end
5660
rescue *CONNECTION_ERRORS
5761
end
5862

@@ -198,9 +202,14 @@ def push(tests)
198202
transaction.lpush(key('queue'), tests) unless tests.empty?
199203
transaction.set(key('total'), @total)
200204
transaction.set(key('master-status'), 'ready')
205+
206+
transaction.expire(key('queue'), config.report_expires_in)
207+
transaction.expire(key('total'), config.report_expires_in)
208+
transaction.expire(key('master-status'), config.report_expires_in)
201209
end
202210
end
203211
register
212+
redis.expire(key('workers'), config.report_expires_in)
204213
rescue *CONNECTION_ERRORS
205214
raise if @master
206215
end

ruby/lib/minitest/queue/runner.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,14 @@ def parser
487487
end
488488
end
489489

490+
help = <<~EOS
491+
Defines how long the test report remain after the test run, in seconds.
492+
Defaults to 28,800 (8 hours)
493+
EOS
494+
opts.on("--report-expires-in SECONDS", Integer, help) do |time|
495+
queue.config.report_expires_in = time
496+
end
497+
490498
opts.separator ""
491499
opts.separator " retry: Replays a previous run in the same order."
492500

ruby/lib/rspec/queue.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,15 @@ def parser(options)
157157
queue_config.max_consecutive_failures = Integer(max)
158158
end
159159

160+
help = <<~EOS
161+
Defines how long the test report remain after the test run, in seconds.
162+
Defaults to 28,800 (8 hours)
163+
EOS
164+
parsed.separator ""
165+
parser.on("--report-expires-in SECONDS", Integer, help) do |time|
166+
queue.config.report_expires_in = time
167+
end
168+
160169
parser
161170
end
162171

0 commit comments

Comments
 (0)