Skip to content

Commit 2bfc49e

Browse files
committed
Worker tries to reconnect to Redis up to 3 times with increasing delay before giving up
1 parent 55d9457 commit 2bfc49e

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
@@ -151,7 +151,7 @@ def work(interval = 5.0, &block)
151151
else
152152
unregister_signal_handlers if !@cant_fork
153153
procline "Processing #{job.queue} since #{Time.now.to_i}"
154-
redis.client.reconnect # Don't share connection with parent
154+
reconnect
155155
perform(job, &block)
156156
exit! unless @cant_fork
157157
end
@@ -224,6 +224,24 @@ def reserve(interval = 5.0)
224224
Job.new(queue.name, job) if queue && job
225225
end
226226

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

test/worker_test.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,40 @@ def self.perform
504504
refute_equal original_connection, Resque.redis.client.connection.instance_variable_get("@sock")
505505
end
506506

507+
it "tries to reconnect three times before giving up" do
508+
begin
509+
class Redis::Client
510+
alias_method :original_reconnect, :reconnect
511+
512+
def reconnect
513+
raise Redis::BaseConnectionError
514+
end
515+
end
516+
517+
class Resque::Worker
518+
alias_method :original_sleep, :sleep
519+
520+
def sleep(duration = nil)
521+
# noop
522+
end
523+
end
524+
525+
@worker.very_verbose = true
526+
stdout, stderr = capture_io { @worker.work(0) }
527+
528+
assert_equal 3, stdout.scan(/retrying/).count
529+
assert_equal 1, stdout.scan(/quitting/).count
530+
ensure
531+
class Redis::Client
532+
alias_method :reconnect, :original_reconnect
533+
end
534+
535+
class Resque::Worker
536+
alias_method :sleep, :original_sleep
537+
end
538+
end
539+
end
540+
507541
it "will call before_pause before it is paused" do
508542
before_pause_called = false
509543
captured_worker = nil

0 commit comments

Comments
 (0)