1

我正在尝试让我的 Rails 应用程序Resque用于管理工人。但是,我想继续使用 ConnectionPool gem。

我在初始化程序中有这个:

puts ENV["REDISTOGO_URL"]

uri = (not ENV["REDISTOGO_URL"].nil?) ? URI.parse(ENV["REDISTOGO_URL"]) : nil

# at this point, debugger confirms $redis is nil
$redis = ConnectionPool::Wrapper.new(:size => 5, :timeout => 3) { 
  if uri.nil?
    Redis.connect
  else
    Redis.connect(:host => uri.host, :port => uri.port, :password => uri.password) 
  end
}

$redis # just put this in here for the debugger
       # At this point, $redis is #<Redis:0x007fb1b0036bf0>
       # when it should be an instance of ConnectionPool::Wrapper

有谁知道为什么$redis不作为实例返回ConnectionPool::Wrapper

我搜索了所有 gems 源代码,它没有设置$redis. 在 ConnectionPool 的源代码中,我没有找到任何会返回实例Redis而不是自身的东西。

这只发生在我从 DelayedJob 切换到 Resque 时。所以,这似乎是问题所在。然而,我不知所措。

我正在使用独角兽。这是config.

worker_processes 2
timeout 30
preload_app true

before_fork do |server, worker|
  # Replace with MongoDB or whatever
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.disconnect!
    Rails.logger.info('Disconnected from ActiveRecord')
  end

  # If you are using Redis but not Resque, change this
  if defined?(Resque)
    Resque.redis.quit
    Rails.logger.info('Disconnected from Redis')
  end

  sleep 1
end

after_fork do |server, worker|
  # Replace with MongoDB or whatever
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.establish_connection
    Rails.logger.info('Connected to ActiveRecord')
  end

  # If you are using Redis but not Resque, change this
  if defined?(Resque)
    # Yes, commented the Resque out for debugging, still get the same problem.
    #Resque.redis = ENV['REDISTOGO_URL']
    Rails.logger.info('Connected to Redis')
  end
end

最后,Procfile:

web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
worker: env TERM_CHILD=1 QUEUE=* bundle exec rake resque:work

foreman在我的开发环境中使用。

任何帮助是极大的赞赏。

4

2 回答 2

1

From the docs:

You can use ConnectionPool::Wrapper to wrap a single global connection.

I looks like the ConnectionPool::Wrapper is meant to wrap a single connection to Redis as a convenience for migrating large applications from using Redis directly to using ConnectionPools

If you call $redis.with, you get the #with defined by ConnectionPool

To get an actual connection pool, just change your

ConnectionPool::Wrapper.new(:size => 5, :timeout => 3) { #redis logic }

to

ConnectionPool.new(:size => 5, :timeout => 3) { #redis logic }
于 2013-04-03T15:54:58.007 回答
1

ConnectionPool::Wrapper 在内部创建一个普通的 ConnectionPool 对象,并在包装​​器上调用任何方法时使用 method_missing 自动从该池中签出/签入。

method_missing 的这种使用包括对inspect、 或class或任何数量的方法的调用,这些方法通常用于尝试查看对象或确定其类型。

require 'connection_pool'

class MyClass
  def foo
    'bar'
  end
end

obj = MyClass.new
obj.respond_to?(:foo) # true
obj.respond_to?(:with) # false  

wrapper = ConnectionPool::Wrapper.new { MyClass.new }
wrapper.respond_to?(:foo) # true
wrapper.respond_to?(:with) # also true! 'with' is a method on ConnectionPool::Wrapper

您确实有一个 ConnectionPool::Wrapper 实例,只是有点难以分辨。

于 2013-09-25T02:18:46.070 回答