Class: RedisClient::SentinelConfig

Inherits:
Object
  • Object
show all
Includes:
Config::Common
Defined in:
lib/redis_client/sentinel_config.rb

Constant Summary collapse

SENTINEL_DELAY =
0.25
DEFAULT_RECONNECT_ATTEMPTS =
2

Instance Attribute Summary collapse

Attributes included from Config::Common

#circuit_breaker, #command_builder, #connect_timeout, #custom, #db, #driver, #id, #inherit_socket, #middlewares_stack, #protocol, #read_timeout, #ssl, #ssl_params, #write_timeout

Instance Method Summary collapse

Methods included from Config::Common

#connection_prelude, #new_client, #new_pool, #password, #retriable?, #server_url, #ssl_context, #username

Constructor Details

#initialize(sentinels:, sentinel_password: nil, sentinel_username: nil, role: :master, name: nil, url: nil, **client_config) ⇒ SentinelConfig

Returns a new instance of SentinelConfig.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/redis_client/sentinel_config.rb', line 12

def initialize(
  sentinels:,
  sentinel_password: nil,
  sentinel_username: nil,
  role: :master,
  name: nil,
  url: nil,
  **client_config
)
  unless i(master replica slave).include?(role.to_sym)
    raise ArgumentError, "Expected role to be either :master or :replica, got: #{role.inspect}"
  end

  # Track whether SSL was explicitly provided by user
  ssl_explicitly_set = client_config.key?(:ssl)

  if url
    url_config = URLConfig.new(url)
    client_config = {
      username: url_config.username,
      password: url_config.password,
      db: url_config.db,
      ssl: url_config.ssl?,
    }.compact.merge(client_config)
    name ||= url_config.host
  end

  @name = name
  unless @name
    raise ArgumentError, "RedisClient::SentinelConfig requires either a name or an url with a host"
  end

  @to_list_of_hash = @to_hash = nil
  password = if sentinel_password && !sentinel_password.respond_to?(:call)
    ->(_) { sentinel_password }
  else
    sentinel_password
  end
  @extra_config = {
    username: sentinel_username,
    password: password,
    db: nil,
  }
  if client_config[:protocol] == 2
    @extra_config[:protocol] = client_config[:protocol]
    @to_list_of_hash = lambda do |may_be_a_list|
      if may_be_a_list.is_a?(Array)
        may_be_a_list.map { |l| l.each_slice(2).to_h }
      else
        may_be_a_list
      end
    end
  end

  @sentinels = {}.compare_by_identity
  @role = role.to_sym
  @mutex = Mutex.new
  @config = nil

  client_config[:reconnect_attempts] ||= DEFAULT_RECONNECT_ATTEMPTS
  @client_config = client_config || {}
  @sentinel_client_config = @client_config.dup
  # Only remove SSL from sentinel config if it was derived from URL,
  # not if explicitly set by user.
  @sentinel_client_config.delete(:ssl) unless ssl_explicitly_set
  super(**client_config)
  @sentinel_configs = sentinels_to_configs(sentinels)
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



10
11
12
# File 'lib/redis_client/sentinel_config.rb', line 10

def name
  @name
end

Instance Method Details

#check_role!(role) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/redis_client/sentinel_config.rb', line 118

def check_role!(role)
  if @role == :master
    unless role == "master"
      sleep SENTINEL_DELAY
      raise FailoverError, "Expected to connect to a master, but the server is a replica"
    end
  else
    unless role == "slave"
      sleep SENTINEL_DELAY
      raise FailoverError, "Expected to connect to a replica, but the server is a master"
    end
  end
end

#hostObject



97
98
99
# File 'lib/redis_client/sentinel_config.rb', line 97

def host
  config.host
end

#pathObject



105
106
107
# File 'lib/redis_client/sentinel_config.rb', line 105

def path
  nil
end

#portObject



101
102
103
# File 'lib/redis_client/sentinel_config.rb', line 101

def port
  config.port
end

#resetObject



87
88
89
90
91
# File 'lib/redis_client/sentinel_config.rb', line 87

def reset
  @mutex.synchronize do
    @config = nil
  end
end

#resolved?Boolean

Returns:



132
133
134
135
136
# File 'lib/redis_client/sentinel_config.rb', line 132

def resolved?
  @mutex.synchronize do
    !!@config
  end
end

#retry_connecting?(attempt, error) ⇒ Boolean

Returns:



109
110
111
112
# File 'lib/redis_client/sentinel_config.rb', line 109

def retry_connecting?(attempt, error)
  reset unless error.is_a?(TimeoutError)
  super
end

#sentinel?Boolean

Returns:



114
115
116
# File 'lib/redis_client/sentinel_config.rb', line 114

def sentinel?
  true
end

#sentinelsObject



81
82
83
84
85
# File 'lib/redis_client/sentinel_config.rb', line 81

def sentinels
  @mutex.synchronize do
    @sentinel_configs.dup
  end
end

#server_keyObject



93
94
95
# File 'lib/redis_client/sentinel_config.rb', line 93

def server_key
  config.server_key
end