class EventMachine::Hiredis::BaseClient

Emits the following events

Attributes

db[R]
host[R]
password[R]
port[R]

Public Class Methods

new(host = 'localhost', port = 6379, password = nil, db = nil) click to toggle source
# File lib/em-hiredis/base_client.rb, line 19
def initialize(host = 'localhost', port = 6379, password = nil, db = nil)
  @host, @port, @password, @db = host, port, password, db
  @defs = []
  @command_queue = []

  @reconnect_failed_count = 0
  @reconnect_timer = nil
  @failed = false

  @inactive_seconds = 0

  self.on(:failed) {
    @failed = true
    @command_queue.each do |df, _, _|
      df.fail(Error.new("Redis connection in failed state"))
    end
    @command_queue = []
  }
end

Public Instance Methods

auth(password, &blk) click to toggle source
# File lib/em-hiredis/base_client.rb, line 171
def auth(password, &blk)
  @password = password
  method_missing(:auth, password, &blk)
end
close_connection() click to toggle source
# File lib/em-hiredis/base_client.rb, line 176
def close_connection
  EM.cancel_timer(@reconnect_timer) if @reconnect_timer
  @auto_reconnect = false
  @connection.close_connection_after_writing
end
configure(uri_string) click to toggle source

Configure the redis connection to use

In usual operation, the uri should be passed to initialize. This method is useful for example when failing over to a slave connection at runtime

# File lib/em-hiredis/base_client.rb, line 44
def configure(uri_string)
  uri = URI(uri_string)

  if uri.scheme == "unix"
    @host = uri.path
    @port = nil
  else
    @host = uri.host
    @port = uri.port
    @password = uri.password
    path = uri.path[1..-1]
    @db = path.to_i # Empty path => 0
  end
end
configure_inactivity_check(trigger_secs, response_timeout) click to toggle source

Starts an inactivity checker which will ping redis if nothing has been heard on the connection for `trigger_secs` seconds and forces a reconnect after a further `response_timeout` seconds if we still don't hear anything.

# File lib/em-hiredis/base_client.rb, line 193
def configure_inactivity_check(trigger_secs, response_timeout)
  raise ArgumentError('trigger_secs must be > 0') unless trigger_secs.to_i > 0
  raise ArgumentError('response_timeout must be > 0') unless response_timeout.to_i > 0

  @inactivity_trigger_secs = trigger_secs.to_i
  @inactivity_response_timeout = response_timeout.to_i

  # Start the inactivity check now only if we're already conected, otherwise
  # the connected event will schedule it.
  schedule_inactivity_checks if @connected
end
connect() click to toggle source
# File lib/em-hiredis/base_client.rb, line 72
def connect
  @auto_reconnect = true
  @connection = EM.connect(@host, @port, Connection, @host, @port)

  @connection.on(:closed) do
    cancel_inactivity_checks
    if @connected
      @defs.each { |d| d.fail(Error.new("Redis disconnected")) }
      @defs = []
      @deferred_status = nil
      @connected = false
      if @auto_reconnect
        # Next tick avoids reconnecting after for example EM.stop
        EM.next_tick { reconnect }
      end
      emit(:disconnected)
      EM::Hiredis.logger.info("#{@connection} Disconnected")
    else
      if @auto_reconnect
        @reconnect_failed_count += 1
        @reconnect_timer = EM.add_timer(EM::Hiredis.reconnect_timeout) {
          @reconnect_timer = nil
          reconnect
        }
        emit(:reconnect_failed, @reconnect_failed_count)
        EM::Hiredis.logger.info("#{@connection} Reconnect failed")

        if @reconnect_failed_count >= 4
          emit(:failed)
          self.fail(Error.new("Could not connect after 4 attempts"))
        end
      end
    end
  end

  @connection.on(:connected) do
    @connected = true
    @reconnect_failed_count = 0
    @failed = false

    auth(@password) if @password
    select(@db) unless @db == 0

    @command_queue.each do |df, command, args|
      @connection.send_command(command, args)
      @defs.push(df)
    end
    @command_queue = []

    schedule_inactivity_checks

    emit(:connected)
    EM::Hiredis.logger.info("#{@connection} Connected")
    succeed

    if @reconnecting
      @reconnecting = false
      emit(:reconnected)
    end
  end

  @connection.on(:message) do |reply|
    if RuntimeError === reply
      raise "Replies out of sync: #{reply.inspect}" if @defs.empty?
      deferred = @defs.shift
      error = RedisError.new(reply.message)
      error.redis_error = reply
      deferred.fail(error) if deferred
    else
      @inactive_seconds = 0
      handle_reply(reply)
    end
  end

  @connected = false
  @reconnecting = false

  return self
end
connected?() click to toggle source
# File lib/em-hiredis/base_client.rb, line 162
def connected?
  @connected
end
pending_commands?() click to toggle source

Indicates that commands have been sent to redis but a reply has not yet been received

This can be useful for example to avoid stopping the eventmachine reactor while there are outstanding commands

# File lib/em-hiredis/base_client.rb, line 158
def pending_commands?
  @connected && @defs.size > 0
end
reconnect!(new_uri = nil) click to toggle source

Disconnect then reconnect the redis connection.

Pass optional uri - e.g. to connect to a different redis server. Any pending redis commands will be failed, but during the reconnection new commands will be queued and sent after connected.

# File lib/em-hiredis/base_client.rb, line 65
def reconnect!(new_uri = nil)
  @connection.close_connection
  configure(new_uri) if new_uri
  @auto_reconnect = true
  EM.next_tick { reconnect_connection }
end
reconnect_connection() click to toggle source

Note: This method doesn't disconnect if already connected. You probably want to use `reconnect!`

# File lib/em-hiredis/base_client.rb, line 184
def reconnect_connection
  @auto_reconnect = true
  EM.cancel_timer(@reconnect_timer) if @reconnect_timer
  reconnect
end
select(db, &blk) click to toggle source
# File lib/em-hiredis/base_client.rb, line 166
def select(db, &blk)
  @db = db
  method_missing(:select, db, &blk)
end