Class: Redis::Client::Connector::Sentinel

Inherits:
Redis::Client::Connector show all
Defined in:
lib/redis/client.rb

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Sentinel

Returns a new instance of Sentinel.



465
466
467
468
469
470
471
# File 'lib/redis/client.rb', line 465

def initialize(options)
  super(options)

  @sentinels = options.fetch(:sentinels).dup
  @role = options[:role].to_s
  @master = options[:host]
end

Instance Method Details

#check(client) ⇒ Object



473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'lib/redis/client.rb', line 473

def check(client)
  # Check the instance is really of the role we are looking for.
  # We can't assume the command is supported since it was introduced
  # recently and this client should work with old stuff.
  begin
    role = client.call([:role])[0]
  rescue Redis::CommandError
    # Assume the test is passed if we can't get a reply from ROLE...
    role = @role
  end

  if role != @role
    disconnect
    raise ConnectionError, "Instance role mismatch. Expected #{@role}, got #{role}."
  end
end

#resolveObject



490
491
492
493
494
495
496
497
498
499
500
501
# File 'lib/redis/client.rb', line 490

def resolve
  result = case @role
           when "master"
             resolve_master
           when "slave"
             resolve_slave
           else
             raise ArgumentError, "Unknown instance role #{@role}"
           end

  result || (raise ConnectionError, "Unable to fetch #{@role} via Sentinel.")
end

#resolve_masterObject



523
524
525
526
527
528
529
# File 'lib/redis/client.rb', line 523

def resolve_master
  sentinel_detect do |client|
    if reply = client.call(["sentinel", "get-master-addr-by-name", @master])
      {:host => reply[0], :port => reply[1]}
    end
  end
end

#resolve_slaveObject



531
532
533
534
535
536
537
538
539
# File 'lib/redis/client.rb', line 531

def resolve_slave
  sentinel_detect do |client|
    if reply = client.call(["sentinel", "slaves", @master])
      slave = Hash[*reply.sample]

      {:host => slave.fetch("ip"), :port => slave.fetch("port")}
    end
  end
end

#sentinel_detectObject



503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
# File 'lib/redis/client.rb', line 503

def sentinel_detect
  @sentinels.each do |sentinel|
    client = Client.new(:host => sentinel[:host], :port => sentinel[:port], :timeout => 0.3)

    begin
      if result = yield(client)
        # This sentinel responded. Make sure we ask it first next time.
        @sentinels.delete(sentinel)
        @sentinels.unshift(sentinel)

        return result
      end
    ensure
      client.disconnect
    end
  end

  return nil
end