ryanlecompte / redis_failover

redis_failover is a ZooKeeper-based automatic master/slave failover solution for Ruby.
http://github.com/ryanlecompte/redis_failover
MIT License
539 stars 65 forks source link

Define 'call' method on client to enable use with redis-store #54

Closed jcrivera closed 11 years ago

jcrivera commented 11 years ago

The redis-store gem implements a caching strategy for Rails, but swapping in RedisFailover::Client for its default standard Redis client results in errors when redis-store tries to use the "call" method, which it expects to be available, and allows it to programmatically invoke a method, passed as a symbol argument.

So this offered solution defines the "call" method for RedisFailover::Client and delegates it to the already existing "dispatch" method.

ryanlecompte commented 11 years ago

Looks great! Thanks.

cleblanc87 commented 11 years ago

@jcrivera can I ask how you were able to integrate redis_failover with redis-store? I have been unsuccessful getting that setup with rails 4.

jcrivera commented 11 years ago

Sure, no problem. I'll have to take a look back at that code to refresh my memory and get back to you.

On Fri, Sep 6, 2013 at 10:07 PM, Chris notifications@github.com wrote:

@jcrivera https://github.com/jcrivera can I ask how you were able to integrate redis_failover with redis-store? I have been unsuccessful getting that setup with rails 4.

— Reply to this email directly or view it on GitHubhttps://github.com/ryanlecompte/redis_failover/pull/54#issuecomment-23979649 .

cleblanc87 commented 11 years ago

Thank you very much!

jcrivera commented 11 years ago

@cleblanc87 Ok, it turned out there were two parts to this - one was the PR that @ryanlecompte merged back into the redis_failover project, defining "call" for the failover-integrated implementation of the redis client. However, you're correct that another step was necessary to get redis-store to use it. BTW, this is in rails 3 still, so I can't be sure it will work just the same with rails 4 yet, but here is what we did:

First, we monkey-patch ActiveSupport::Cache to add a reset_client method on the RedisStore class, allowing us to change the internal redis-client object, like so:

module ActiveSupport::Cache
  class RedisStore
    def reset_client(client)
      @data.instance_variable_set('@client', client)
    end
  end
end

This is done because RedisStore as it exists currently, has no interface allowing the redis client instance it holds to be set by anything other than specifying a connection string...

ContactsCore::Application.configure do
  ...
  config.cache_store = :redis_store, "redis://<host>:<port>"
  ...
end

...but we want to inject our own choice of redis client (the redis_failover version implementation).

Then, there's nothing to do but call the new reset_client method with an instance of the redis_failover redis client in an initializer, as below (RedisClient is our wrapper for pooling redis connections and config, and "connect" returns an instance of redis_failover client):

@redis_master = RedisClient.connect
if RedisFailover::Client === @redis_master
  Rails.cache.reset_client(@redis_master)
end

I hope that's helpful. These extra changes seemed like outside of the scope of redis_failover, even though they, or something like them, turn out to be necessary for integrating it with redis-store. Ideally, redis-store could be patched to allow easier configuration of redis client implementation, but I have a feeling getting this into rails would be much more involved than doing a quick monkey-patch.