Skip to content

Commit 8dc2803

Browse files
engwanHeinrich Lee Yu
and
Heinrich Lee Yu
authored
Fix poll interval not changing based on process count (#5513)
We should not memoize the value of `scaled_poll_interval` because this changes based on the number of Sidekiq processes Co-authored-by: Heinrich Lee Yu <[email protected]>
1 parent ea9c86f commit 8dc2803

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

lib/sidekiq/scheduled.rb

+9-6
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,16 @@ def random_poll_interval
147147
# As we run more processes, the scheduling interval average will approach an even spread
148148
# between 0 and poll interval so we don't need this artifical boost.
149149
#
150-
if process_count < 10
150+
count = process_count
151+
interval = poll_interval_average(count)
152+
153+
if count < 10
151154
# For small clusters, calculate a random interval that is ±50% the desired average.
152-
poll_interval_average * rand + poll_interval_average.to_f / 2
155+
interval * rand + interval.to_f / 2
153156
else
154157
# With 10+ processes, we should have enough randomness to get decent polling
155158
# across the entire timespan
156-
poll_interval_average * rand
159+
interval * rand
157160
end
158161
end
159162

@@ -170,14 +173,14 @@ def random_poll_interval
170173
# the same time: the thundering herd problem.
171174
#
172175
# We only do this if poll_interval_average is unset (the default).
173-
def poll_interval_average
174-
@config[:poll_interval_average] ||= scaled_poll_interval
176+
def poll_interval_average(count)
177+
@config[:poll_interval_average] || scaled_poll_interval(count)
175178
end
176179

177180
# Calculates an average poll interval based on the number of known Sidekiq processes.
178181
# This minimizes a single point of failure by dispersing check-ins but without taxing
179182
# Redis if you run many Sidekiq processes.
180-
def scaled_poll_interval
183+
def scaled_poll_interval(process_count)
181184
process_count * @config[:average_scheduled_poll_interval]
182185
end
183186

test/test_scheduled.rb

+23-4
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,35 @@ def with_sidekiq_option(name, value)
125125
end
126126
end
127127

128-
it "calculates an average poll interval based on the number of known Sidekiq processes" do
128+
it "generates random intervals based on the number of known Sidekiq processes" do
129129
with_sidekiq_option(:average_scheduled_poll_interval, 10) do
130-
3.times do |i|
130+
intervals_count = 500
131+
132+
# Start with 10 processes
133+
10.times do |i|
131134
Sidekiq.redis do |conn|
132135
conn.sadd("processes", ["process-#{i}"])
133-
conn.hset("process-#{i}", "info", "")
134136
end
135137
end
136138

137-
assert_equal 30, @poller.send(:scaled_poll_interval)
139+
intervals = Array.new(intervals_count) { @poller.send(:random_poll_interval) }
140+
assert intervals.all? { |x| x.between?(0, 100) }
141+
142+
# Reduce to 3 processes
143+
(3..9).each do |i|
144+
Sidekiq.redis do |conn|
145+
conn.srem("processes", ["process-#{i}"])
146+
end
147+
end
148+
149+
intervals = Array.new(intervals_count) { @poller.send(:random_poll_interval) }
150+
assert intervals.all? { |x| x.between?(15, 45) }
151+
end
152+
end
153+
154+
it "calculates an average poll interval based on a given number of processes" do
155+
with_sidekiq_option(:average_scheduled_poll_interval, 10) do
156+
assert_equal 30, @poller.send(:scaled_poll_interval, 3)
138157
end
139158
end
140159
end

0 commit comments

Comments
 (0)