mperham / connection_pool

Generic connection pooling for Ruby
MIT License
1.63k stars 143 forks source link

Nested checkouts support #99

Closed rafaelsales closed 6 years ago

rafaelsales commented 6 years ago

Hi,

In the scenario where I need to access redis within a subscribe callback, I need to use nest call of pool.with, which doesn't checkout another connection.

Example:

require 'redis'
require 'connection_pool'

def redis_pool
  @redis_pool ||= ConnectionPool.new { Redis.new }
end

def listen
  redis_pool.with do |redis|
    redis.subscribe('pool', 'non-pool') do |on|
      on.message do |channel, _message|
        redis_pool.with do |redis2|
          puts redis2.object_id == redis.object_id
          puts redis2.info # raises error because it's trying to use the subscribe connection
        end
      end
    end
  end
rescue => e
  puts e.message
end

def publish
  redis_pool.with do |redis|
    redis.publish('pool', 'hello')
  end
end

Thread.new { listen }
sleep 1
publish
sleep 1

# Output:
# true
# Error: Redis::CommandError ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT allowed in this context

The workaround I've thought about was to always use Redis.new when using it to subscribe.

Are there plans to have a nicer usage for this scenario?

mperham commented 6 years ago

It's possible with could take a force_new boolean to override the default reuse logic. Otherwise, since listen is likely a long-running method, I'd suggest it have its own Redis connection and the message handling use the connection pool as normal.

rafaelsales commented 6 years ago

since listen is likely a long-running method, I'd suggest it have its own Redis connection

That's true. I'll go for this solution

Thanks