Skip to content

Commit 805ff70

Browse files
committed
Refactor poll interval handling to use initial interval as minimum
Updated the Flipper::Poller to ensure that the poll interval respects the initial interval as a minimum value. Adjusted tests to verify behavior when the poll-interval header is lower, higher, or equal to the initial interval, ensuring correct enforcement of minimum limits.
1 parent 1439892 commit 805ff70

File tree

2 files changed

+106
-6
lines changed

2 files changed

+106
-6
lines changed

lib/flipper/poller.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def initialize(options = {})
3434
@shutdown_requested = Concurrent::AtomicBoolean.new(false)
3535

3636
self.interval = options.fetch(:interval, 10)
37+
@initial_interval = @interval
3738

3839
@start_automatically = options.fetch(:start_automatically, true)
3940

@@ -87,7 +88,7 @@ def sync
8788
end
8889

8990
if interval = response["poll-interval"]
90-
self.interval = interval
91+
self.interval = [Flipper::Typecast.to_float(interval), @initial_interval].max
9192
end
9293
end
9394
end

spec/flipper/poller_spec.rb

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
described_class.new(
1111
remote_adapter: remote_adapter,
1212
start_automatically: false,
13-
interval: Float::INFINITY
13+
interval: 3600 # 1 hour
1414
)
1515
end
1616

@@ -172,7 +172,7 @@
172172
end
173173
end
174174

175-
context "when poll-interval header is present" do
175+
context "when poll-interval header is lower than initial interval" do
176176
before do
177177
stub_request(:get, "#{url}/features?exclude_gate_names=true")
178178
.to_return(
@@ -191,14 +191,22 @@
191191
)
192192
end
193193

194-
it "adjusts the poll interval" do
195-
expect(subject.interval).to eq(Float::INFINITY)
194+
it "uses the initial interval as minimum" do
195+
expect(subject.interval).to eq(3600.0)
196196
subject.sync
197-
expect(subject.interval).to eq(30.0)
197+
expect(subject.interval).to eq(3600.0) # Keeps 3600 because it's the initial interval
198198
end
199199
end
200200

201201
context "when poll-interval header is below minimum" do
202+
subject do
203+
described_class.new(
204+
remote_adapter: remote_adapter,
205+
start_automatically: false,
206+
interval: 10 # Set initial to minimum
207+
)
208+
end
209+
202210
before do
203211
stub_request(:get, "#{url}/features?exclude_gate_names=true")
204212
.to_return(
@@ -218,11 +226,102 @@
218226
end
219227

220228
it "enforces minimum poll interval" do
229+
expect(subject.interval).to eq(10.0)
221230
subject.sync
231+
# Header says 5, minimum is 10, initial is 10, so max(5->10, 10) = 10
222232
expect(subject.interval).to eq(Flipper::Poller::MINIMUM_POLL_INTERVAL)
223233
end
224234
end
225235

236+
context "when poll-interval header is higher than initial interval" do
237+
subject do
238+
described_class.new(
239+
remote_adapter: remote_adapter,
240+
start_automatically: false,
241+
interval: 20
242+
)
243+
end
244+
245+
before do
246+
stub_request(:get, "#{url}/features?exclude_gate_names=true")
247+
.to_return(
248+
status: 200,
249+
body: JSON.generate(
250+
features: [
251+
{
252+
key: "polling",
253+
gates: [
254+
{ key: "boolean", value: true }
255+
]
256+
}
257+
]
258+
),
259+
headers: { "poll-interval" => "60" }
260+
)
261+
end
262+
263+
it "updates to the higher interval from header" do
264+
expect(subject.interval).to eq(20.0)
265+
subject.sync
266+
expect(subject.interval).to eq(60.0) # Uses 60 because it's higher than initial 20
267+
end
268+
end
269+
270+
context "when poll-interval header can decrease back to initial interval" do
271+
subject do
272+
described_class.new(
273+
remote_adapter: remote_adapter,
274+
start_automatically: false,
275+
interval: 10
276+
)
277+
end
278+
279+
before do
280+
# First sync increases interval to 60
281+
stub_request(:get, "#{url}/features?exclude_gate_names=true")
282+
.to_return(
283+
status: 200,
284+
body: JSON.generate(
285+
features: [
286+
{
287+
key: "polling",
288+
gates: [
289+
{ key: "boolean", value: true }
290+
]
291+
}
292+
]
293+
),
294+
headers: { "poll-interval" => "60" }
295+
).times(1).then
296+
.to_return(
297+
status: 200,
298+
body: JSON.generate(
299+
features: [
300+
{
301+
key: "polling",
302+
gates: [
303+
{ key: "boolean", value: true }
304+
]
305+
}
306+
]
307+
),
308+
headers: { "poll-interval" => "10" }
309+
)
310+
end
311+
312+
it "allows interval to go back down to initial after being increased" do
313+
expect(subject.interval).to eq(10.0)
314+
315+
# First sync: header says 60, initial is 10, so use 60
316+
subject.sync
317+
expect(subject.interval).to eq(60.0)
318+
319+
# Second sync: header says 10, initial is 10, so use 10
320+
subject.sync
321+
expect(subject.interval).to eq(10.0)
322+
end
323+
end
324+
226325
context "when poll-interval header is missing" do
227326
before do
228327
stub_request(:get, "#{url}/features?exclude_gate_names=true")

0 commit comments

Comments
 (0)