lib/redis_failover/client.rb in redis_failover-0.5.2 vs lib/redis_failover/client.rb in redis_failover-0.5.3

- old
+ new

@@ -3,10 +3,11 @@ module RedisFailover # Redis failover-aware client. class Client include Util + ZNODE_UPDATE_TIMEOUT = 9 RETRY_WAIT_TIME = 3 REDIS_READ_OPS = Set[ :echo, :exists, :get, @@ -63,11 +64,11 @@ # Creates a new failover redis client. # # Options: # - # :zkservers - comma-separated zookeeper host:port pairs (required) + # :zkservers - comma-separated ZooKeeper host:port pairs (required) # :znode_path - the Znode path override for redis server list (optional) # :password - password for redis nodes (optional) # :namespace - namespace for redis nodes (optional) # :logger - logger override (optional) # :retry_failure - indicate if failures should be retried (default true) @@ -107,10 +108,11 @@ private def setup_zookeeper_client @zkclient = ZkClient.new(@zkservers) + update_znode_timestamp # when session expires, purge client list @zkclient.on_session_expiration do purge_clients end @@ -126,14 +128,16 @@ end # register a watcher for future changes @zkclient.watcher.register(@znode) do |event| if event.node_created? || event.node_changed? + update_znode_timestamp build_clients elsif event.node_deleted? - @zkclient.stat(@znode, :watch => true) + update_znode_timestamp purge_clients + @zkclient.stat(@znode, :watch => true) else logger.error("Unknown ZK node event: #{event.inspect}") end end end @@ -141,23 +145,27 @@ def redis_operation?(method) Redis.public_instance_methods(false).include?(method) end def dispatch(method, *args, &block) + unless recently_heard_from_node_manager? + purge_clients + raise MissingNodeManagerError.new(ZNODE_UPDATE_TIMEOUT) + end + verify_supported!(method) tries = 0 - begin if REDIS_READ_OPS.include?(method) # send read operations to a slave slave.send(method, *args, &block) else # direct everything else to master master.send(method, *args, &block) end rescue *CONNECTIVITY_ERRORS => ex - logger.error("Error while handling operation `#{method}` - #{ex.message}") + logger.error("Error while handling operation `#{method}` - #{ex.inspect}") logger.error(ex.backtrace.join("\n")) if tries < @max_retries tries += 1 build_clients @@ -200,11 +208,11 @@ new_slaves = new_clients_for(*nodes[:slaves]) @master = new_master @slaves = new_slaves rescue StandardError, *CONNECTIVITY_ERRORS => ex purge_clients - logger.error("Failed to fetch nodes from #{@zkservers} - #{ex.message}") + logger.error("Failed to fetch nodes from #{@zkservers} - #{ex.inspect}") logger.error(ex.backtrace.join("\n")) if tries < @max_retries tries += 1 sleep(RETRY_WAIT_TIME) && retry @@ -289,8 +297,17 @@ logger.info("Purging current redis clients") disconnect(@master, *@slaves) @master = nil @slaves = [] end + end + + def update_znode_timestamp + @last_znode_timestamp = Time.now + end + + def recently_heard_from_node_manager? + return false unless @last_znode_timestamp + Time.now - @last_znode_timestamp <= ZNODE_UPDATE_TIMEOUT end end end