Skip to content

Commit b0627ec

Browse files
authored
test: Avoid hang in big segment status polling specs (#440)
1 parent 7a92bed commit b0627ec

2 files changed

Lines changed: 26 additions & 16 deletions

File tree

.github/workflows/build-gem.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ on:
1616
jobs:
1717
build-gem:
1818
runs-on: ubuntu-latest
19+
timeout-minutes: 20
1920

2021
env:
2122
LD_SKIP_DATABASE_TESTS: 0

spec/impl/big_segments_spec.rb

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,25 @@ def with_manager(config)
3232
end
3333
end
3434

35+
#
36+
# Waits for a status matching the given predicate, ignoring any statuses that were already
37+
# queued. Observers are only notified when the status changes, and the manager starts polling
38+
# as soon as it is constructed, so a test cannot assume which statuses it will observe.
39+
#
40+
def next_status_matching(statuses, timeout = 5)
41+
deadline = Time.now + timeout
42+
loop do
43+
begin
44+
status = statuses.pop(true)
45+
rescue ThreadError
46+
raise "timed out waiting for expected status" if Time.now >= deadline
47+
sleep 0.01
48+
next
49+
end
50+
return status if yield status
51+
end
52+
end
53+
3554
context "membership query" do
3655
it "with uncached result and healthy status" do
3756
expected_membership = { 'key1' => true, 'key2' => true }
@@ -178,18 +197,13 @@ def with_manager(config)
178197
with_manager(BigSegmentsConfig.new(store: store, status_poll_interval: 0.01)) do |m|
179198
m.status_provider.add_observer(SimpleObserver.new(->(value) { statuses << value }))
180199

181-
status1 = statuses.pop
182-
expect(status1.available).to be(true)
200+
expect(m.status_provider.status.available).to be(true)
183201

184202
should_fail.make_true
185-
186-
status2 = statuses.pop
187-
expect(status2.available).to be(false)
203+
next_status_matching(statuses) { |status| !status.available }
188204

189205
should_fail.make_false
190-
191-
status3 = statuses.pop
192-
expect(status3.available).to be(true)
206+
next_status_matching(statuses) { |status| status.available }
193207
end
194208
end
195209

@@ -205,18 +219,13 @@ def with_manager(config)
205219
with_manager(BigSegmentsConfig.new(store: store, status_poll_interval: 0.01)) do |m|
206220
m.status_provider.add_observer(SimpleObserver.new(->(value) { statuses << value }))
207221

208-
status1 = statuses.pop
209-
expect(status1.stale).to be(false)
222+
expect(m.status_provider.status.stale).to be(false)
210223

211224
should_be_stale.make_true
212-
213-
status2 = statuses.pop
214-
expect(status2.stale).to be(true)
225+
next_status_matching(statuses) { |status| status.stale }
215226

216227
should_be_stale.make_false
217-
218-
status3 = statuses.pop
219-
expect(status3.stale).to be(false)
228+
next_status_matching(statuses) { |status| !status.stale }
220229
end
221230
end
222231
end

0 commit comments

Comments
 (0)