Невозможно спасти от отказа подключения Redis - PullRequest
7 голосов
/ 05 октября 2011

Я пытаюсь написать функцию, которая пытается подключиться к Redis, используя настройки TCP по умолчанию, и, если это не удается, пытается подключиться к Redis через сокет unix.Я намереваюсь создать единый сценарий подключения, который будет работать на всех моих системах, некоторые из которых используют TCP, а другие используют сокеты.

Однако я не могу спастись от сбоя TCP-соединения.Вот мой тестовый скрипт.

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"

Блок rescue никогда не выполняется и вместо этого возникает исключение.Вот вывод этого скрипта.

/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>'

Я проверил, что Redis.new(:path => "/tmp/redis.sock") работает как положено.Я пытался быть более конкретным с моим спасательным блоком, используя rescue Errno::ECONNREFUSED, но безрезультатно.Я не уверен, почему я не могу поймать это исключение.

Есть идеи?

Ответы [ 2 ]

5 голосов
/ 05 октября 2011

Оказывается, исключение не выдается при вызове Redis.new. Исключение не генерируется, пока не будут вызваны определенные методы (в данном случае Redis#keys) для объекта подключения Эта исправленная функция соединения, кажется, делает свое дело.

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
2 голосов
/ 11 декабря 2012

Я обнаружил, что $redis.inspect на самом деле не использовал REDIS соединение. Я заменил его на $redis.keys, и это правильно сгенерировало исключение. Обратите внимание, я работаю на Heroko и передаю переменную окружения REDISTOGO_URL. Затем у меня есть константа REDIS, которую я использую в приложении.

В моем конфиге / 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...