Unable to rescue from Redis connection refusal

I am attempting to write a function which tries to connect to Redis using default TCP settings, and if that fails, tries to connect to Redis through a unix socket. My intent is to have a single connection script that works on all my systems, some of which use TCP and others which use sockets.

However, I can't seem to rescue from the failed TCP connection. Here is my test script.

require "redis"

def r
  begin
    $redis ||= Redis.new
  rescue
    $redis = Redis.new(:path => "/tmp/redis.sock")
  end
end

puts "You have #{r.keys.count} redis keys"

The rescue block never gets executed and instead an exception is raised. Here is the output of this script.

/usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:236:in `rescue in establish_connection': Connection refused - Unable to connect to Redis on 127.0.0.1:6379 (Errno::ECONNREFUSED)
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:222:in `establish_connection'
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:23:in `connect'
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:247:in `ensure_connected'
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:137:in `block in process'
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:206:in `logging'
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:136:in `process'
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:46:in `call'
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis.rb:246:in `block in keys'
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/monitor.rb:201:in `mon_synchronize'
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis.rb:245:in `keys'
    from scripts/redis.rb:11:in `<main>'

I have verified that Redis.new(:path => "/tmp/redis.sock") works as expected. I have tried to be more specific with my rescue block by using rescue Errno::ECONNREFUSED to no avail. I'm not sure why I cannot catch this exception.

Any ideas?


It turns out the exception is not being thrown when calling Redis.new . The exception doesn't get thrown until certain methods (in this case, Redis#keys ) on the connection object are called. This revised connection function appears to do the trick.

require "redis"

def r
  begin
    $redis ||= Redis.new
    $redis.inspect # needed to know if connection failed
  rescue
    $redis = Redis.new(:path => "/tmp/redis.sock")
  end
  $redis
end

I found that $redis.inspect didn't actually exercise the REDIS connection. I replaced it with $redis.keys and that correctly threw the exception. Note, am running on Heroko and it passes in the environment variable REDISTOGO_URL . I then have a constant REDIS that I use throughout the application.

In my config/initializers/redis.rb:

uri = URI.parse(ENV['REDISTOGO_URL'])
begin
  redis ||= Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
  redis.keys # needed to know if connection failed
  REDIS = redis
rescue
  puts("Redis not loaded on #{uri.port}")
  REDIS = nil
end
链接地址: http://www.djcxy.com/p/38788.html

上一篇: 如何在10.10优胜美地上安装therubyracer宝石?

下一篇: 无法从Redis连接拒绝中解救