Skip to content

Commit 2df34fe

Browse files
committed
Worker tries to reconnect to Redis up to 3 times with increasing delay before giving up
Conflicts: test/worker_test.rb
1 parent e586e28 commit 2df34fe

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

lib/resque/worker.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def work(interval = 5.0, &block)
149149
else
150150
unregister_signal_handlers if will_fork? && term_child
151151
procline "Processing #{job.queue} since #{Time.now.to_i}"
152-
redis.client.reconnect # Don't share connection with parent
152+
reconnect
153153
perform(job, &block)
154154
exit! if will_fork?
155155
end
@@ -219,6 +219,24 @@ def reserve
219219
raise e
220220
end
221221

222+
# Reconnect to Redis to avoid sharing a connection with the parent,
223+
# retry up to 3 times with increasing delay before giving up.
224+
def reconnect
225+
tries = 0
226+
begin
227+
redis.client.reconnect
228+
rescue Redis::BaseConnectionError
229+
if (tries += 1) <= 3
230+
log "Error reconnecting to Redis; retrying"
231+
sleep(tries)
232+
retry
233+
else
234+
log "Error reconnecting to Redis; quitting"
235+
raise
236+
end
237+
end
238+
end
239+
222240
# Returns a list of queues to use when searching for a job.
223241
# A splat ("*") means you want every queue (in alpha order) - this
224242
# can be useful for dynamically adding new queues.

test/worker_test.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,40 @@ def self.perform
473473
assert_not_equal original_connection, Resque.redis.client.connection.instance_variable_get("@sock")
474474
end
475475

476+
test "tries to reconnect three times before giving up" do
477+
begin
478+
class Redis::Client
479+
alias_method :original_reconnect, :reconnect
480+
481+
def reconnect
482+
raise Redis::BaseConnectionError
483+
end
484+
end
485+
486+
class Resque::Worker
487+
alias_method :original_sleep, :sleep
488+
489+
def sleep(duration = nil)
490+
# noop
491+
end
492+
end
493+
494+
@worker.very_verbose = true
495+
stdout, stderr = capture_io { @worker.work(0) }
496+
497+
assert_equal 3, stdout.scan(/retrying/).count
498+
assert_equal 1, stdout.scan(/quitting/).count
499+
ensure
500+
class Redis::Client
501+
alias_method :reconnect, :original_reconnect
502+
end
503+
504+
class Resque::Worker
505+
alias_method :sleep, :original_sleep
506+
end
507+
end
508+
end
509+
476510
if !defined?(RUBY_ENGINE) || defined?(RUBY_ENGINE) && RUBY_ENGINE != "jruby"
477511
test "old signal handling is the default" do
478512
rescue_time = nil

0 commit comments

Comments
 (0)