Skip to content

Commit be56e86

Browse files
committed
Introduce config to cap service related polling interval
The maximum polling interval was hardcoded to 24h when set on the job. Though, the exponential backoff calculation did not take this into account. Now the maximum can be configured through `broker_client_maximum_async_poll_interval_seconds` and will be taken into account for all scenarios. Default is still 24h and the config is optional.
1 parent 1924d5d commit be56e86

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-3
lines changed

app/jobs/reoccurring_job.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def polling_interval_seconds
3535

3636
def polling_interval_seconds=(interval)
3737
interval = interval.to_i if interval.is_a? String
38-
@polling_interval = interval.clamp(default_polling_interval_seconds, 24.hours)
38+
@polling_interval = interval.clamp(default_polling_interval_seconds, maximum_polling_interval)
3939
end
4040

4141
private
@@ -58,8 +58,16 @@ def default_polling_exponential_backoff
5858
Config.config.get(:broker_client_async_poll_exponential_backoff_rate)
5959
end
6060

61+
def maximum_polling_interval
62+
Config.config.get(:broker_client_max_async_poll_interval_seconds) || 24.hours
63+
end
64+
6165
def next_execution_in
62-
[polling_interval_seconds, default_polling_interval_seconds * (default_polling_exponential_backoff**retry_number)].max
66+
# use larger polling_interval. Either from job or calculated.
67+
polling_interval = [polling_interval_seconds, default_polling_interval_seconds * (default_polling_exponential_backoff**retry_number)].max
68+
69+
# cap polling interval at maximum_polling_interval
70+
[polling_interval, maximum_polling_interval].min
6371
end
6472

6573
def next_enqueue_would_exceed_maximum_duration?

lib/cloud_controller/config_schemas/base/api_schema.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ class ApiSchema < VCAP::Config
208208
broker_client_default_async_poll_interval_seconds: Integer,
209209
broker_client_max_async_poll_duration_minutes: Integer,
210210
broker_client_async_poll_exponential_backoff_rate: Numeric,
211+
optional(:broker_client_max_async_poll_interval_seconds) => Integer,
211212
optional(:broker_client_response_parser) => {
212213
log_errors: bool,
213214
log_validators: bool,

lib/cloud_controller/config_schemas/base/worker_schema.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class WorkerSchema < VCAP::Config
115115
broker_client_default_async_poll_interval_seconds: Integer,
116116
broker_client_max_async_poll_duration_minutes: Integer,
117117
broker_client_async_poll_exponential_backoff_rate: Numeric,
118+
optional(:broker_client_max_async_poll_interval_seconds) => Integer,
118119
optional(:broker_client_response_parser) => {
119120
log_errors: bool,
120121
log_validators: bool,

spec/unit/jobs/reoccurring_job_spec.rb

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def perform
109109
end
110110
end
111111

112-
it 'keeps the polling interval within the bounds' do
112+
it 'keeps the polling interval within the default bounds' do
113113
job = FakeJob.new
114114
job.polling_interval_seconds = 5
115115
expect(job.polling_interval_seconds).to eq(60)
@@ -118,6 +118,18 @@ def perform
118118
expect(job.polling_interval_seconds).to eq(24.hours)
119119
end
120120

121+
context 'when maximum polling interval is configured' do
122+
before do
123+
TestConfig.config[:broker_client_max_async_poll_interval_seconds] = 1800
124+
end
125+
126+
it 'limits the polling interval to the configured maximum' do
127+
job = FakeJob.new
128+
job.polling_interval_seconds = 10.days
129+
expect(job.polling_interval_seconds).to eq(1800)
130+
end
131+
end
132+
121133
describe 'exponential backoff rate' do
122134
context 'when changing exponential backoff rate only' do
123135
before do
@@ -295,6 +307,51 @@ def perform
295307
execute_all_jobs(expected_successes: 1, expected_failures: 0)
296308
end
297309
end
310+
311+
context 'when maximum polling interval is configured' do
312+
before do
313+
TestConfig.config[:broker_client_max_async_poll_interval_seconds] = 18
314+
end
315+
316+
it 'limits the polling interval to the configured maximum' do
317+
enqueued_time = 0
318+
319+
Timecop.freeze do
320+
Jobs::Enqueuer.new(queue: Jobs::Queues.generic).enqueue_pollable(fake_job)
321+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
322+
enqueued_time = Time.now
323+
end
324+
325+
# the job should run after 15s (15s > 5s (5 * 2^0))
326+
Timecop.freeze(14.seconds.after(enqueued_time)) do
327+
execute_all_jobs(expected_successes: 0, expected_failures: 0)
328+
end
329+
330+
Timecop.freeze(16.seconds.after(enqueued_time)) do
331+
enqueued_time = Time.now
332+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
333+
end
334+
335+
# the job should run after 15s (15s > 10s (5 * 2^1))
336+
Timecop.freeze(14.seconds.after(enqueued_time)) do
337+
execute_all_jobs(expected_successes: 0, expected_failures: 0)
338+
end
339+
340+
Timecop.freeze(16.seconds.after(enqueued_time)) do
341+
enqueued_time = Time.now
342+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
343+
end
344+
345+
# the job should run after 18s (capped at )
346+
Timecop.freeze(17.seconds.after(enqueued_time)) do
347+
execute_all_jobs(expected_successes: 0, expected_failures: 0)
348+
end
349+
350+
Timecop.freeze(19.seconds.after(enqueued_time)) do
351+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
352+
end
353+
end
354+
end
298355
end
299356
end
300357

0 commit comments

Comments
 (0)