Class: Sensu::Redis::Sentinel

Inherits:
Object
  • Object
show all
Includes:
Utilities
Defined in:
lib/sensu/redis/sentinel.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utilities

#ip_address?, #resolve_host, #resolve_hostname

Constructor Details

#initialize(options = {}) ⇒ Sentinel

Initialize the Sentinel connections. The default Redis master name is “mymaster”, which is the same name that the Sensu HA Redis documentation uses. The master name must be set correctly in order for ‘resolve()`.

Parameters:

  • options (Hash) (defaults to: {})

    containing the standard Redis connection settings.



19
20
21
22
23
# File 'lib/sensu/redis/sentinel.rb', line 19

def initialize(options={})
  @master = options[:master_group] || options[:master] || "mymaster"
  @sentinels = []
  connect_to_sentinels(options[:sentinels])
end

Instance Attribute Details

#loggerObject

Returns the value of attribute logger.



10
11
12
# File 'lib/sensu/redis/sentinel.rb', line 10

def logger
  @logger
end

Instance Method Details

#connect_to_sentinel(options = {}) ⇒ Object

Connect to a Sentinel instance and add the connection to ‘@sentinels` to be called upon. This method defaults the Sentinel host and port if either have not been set.

Parameters:

  • options (Hash) (defaults to: {})

    containing the host and port.



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/sensu/redis/sentinel.rb', line 30

def connect_to_sentinel(options={})
  options[:host] ||= "127.0.0.1"
  options[:port] ||= 26379
  resolve_host(options[:host]) do |ip_address|
    if ip_address.nil?
      EM::Timer.new(1) do
        connect_to_sentinel(options)
      end
    else
      @sentinels << EM.connect(ip_address, options[:port].to_i, Client, options)
    end
  end
end

#connect_to_sentinels(sentinels) ⇒ Object

Connect to all Sentinel instances. The Sentinel instance connections will be added to ‘@sentinels`.

Parameters:

  • sentinels (Array)


48
49
50
51
52
# File 'lib/sensu/redis/sentinel.rb', line 48

def connect_to_sentinels(sentinels)
  sentinels.each do |options|
    connect_to_sentinel(options)
  end
end

#create_resolve_timeout(sentinel, seconds) { ... } ⇒ Object

Create a Sentinel master resolve timeout, causing the previous attempt to fail/cancel, while beginning another attempt.

Parameters:

  • sentinel (Object)

    connection.

  • seconds (Integer)

    before timeout.

Yields:

  • callback called when Sentinel resolves the current Redis master address (host & port).



79
80
81
82
83
84
85
# File 'lib/sensu/redis/sentinel.rb', line 79

def create_resolve_timeout(sentinel, seconds, &block)
  EM::Timer.new(seconds) do
    sentinel.fail
    sentinel.succeed
    retry_resolve(&block)
  end
end

#resolve { ... } ⇒ Object

Resolve the current Redis master via Sentinel. The correct Redis master name is required for this method to work.

Yields:

  • callback called when Sentinel resolves the current Redis master address (host & port).



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/sensu/redis/sentinel.rb', line 92

def resolve(&block)
  sentinel = select_a_sentinel
  if sentinel.nil?
    if @logger
      @logger.debug("unable to determine redis master", {
        :reason => "not connected to a redis sentinel"
      })
      @logger.debug("retrying redis master resolution via redis sentinel")
    end
    retry_resolve(&block)
  else
    timeout = create_resolve_timeout(sentinel, 10, &block)
    sentinel.redis_command("sentinel", "get-master-addr-by-name", @master) do |host, port|
      timeout.cancel
      if host && port
        @logger.debug("redis master resolved via redis sentinel", {
          :host => host,
          :port => port.to_i
        }) if @logger
        block.call(host, port.to_i)
      else
        if @logger
          @logger.debug("unable to determine redis master", {
            :reason => "redis sentinel did not return a redis master host and port"
          })
          @logger.debug("retrying redis master resolution via redis sentinel")
        end
        retry_resolve(&block)
      end
    end
  end
end

#retry_resolve { ... } ⇒ Object

Retry ‘resolve()` with the provided callback.

Yields:

  • callback called when Sentinel resolves the current Redis master address (host & port).



66
67
68
69
70
# File 'lib/sensu/redis/sentinel.rb', line 66

def retry_resolve(&block)
  EM::Timer.new(1) do
    resolve(&block)
  end
end

#select_a_sentinelObject

Select a Sentinel connection object that is currently connected.

Returns:

  • (Object)

    Sentinel connection.



58
59
60
# File 'lib/sensu/redis/sentinel.rb', line 58

def select_a_sentinel
  @sentinels.select { |sentinel| sentinel.connected? }.shuffle.first
end