legion-cache 1.3.19 → 1.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/legion-cache.gemspec +1 -1
- data/lib/legion/cache/cacheable.rb +17 -9
- data/lib/legion/cache/helper.rb +27 -33
- data/lib/legion/cache/local.rb +45 -12
- data/lib/legion/cache/memcached.rb +77 -11
- data/lib/legion/cache/memory.rb +27 -5
- data/lib/legion/cache/pool.rb +27 -4
- data/lib/legion/cache/redis.rb +47 -27
- data/lib/legion/cache/redis_hash.rb +23 -8
- data/lib/legion/cache/settings.rb +67 -12
- data/lib/legion/cache/version.rb +1 -1
- data/lib/legion/cache.rb +206 -19
- metadata +3 -3
data/lib/legion/cache/pool.rb
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'connection_pool'
|
|
4
|
+
require 'legion/logging/helper'
|
|
4
5
|
|
|
5
6
|
module Legion
|
|
6
7
|
module Cache
|
|
7
8
|
module Pool
|
|
8
|
-
extend self
|
|
9
|
+
extend self
|
|
10
|
+
extend Legion::Logging::Helper
|
|
9
11
|
|
|
10
12
|
def connected?
|
|
11
13
|
@connected ||= false
|
|
@@ -28,10 +30,12 @@ module Legion
|
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
def close
|
|
31
|
-
client
|
|
33
|
+
return unless @client
|
|
34
|
+
|
|
35
|
+
@client.shutdown(&:close)
|
|
32
36
|
@client = nil
|
|
33
37
|
@connected = false
|
|
34
|
-
|
|
38
|
+
log.info "#{pool_log_name} pool closed"
|
|
35
39
|
end
|
|
36
40
|
|
|
37
41
|
def restart(**opts)
|
|
@@ -42,7 +46,26 @@ module Legion
|
|
|
42
46
|
client_hash[:timeout] = opts[:timeout] if opts.key? :timeout
|
|
43
47
|
client(**client_hash)
|
|
44
48
|
@connected = true
|
|
45
|
-
|
|
49
|
+
log.info "#{pool_log_name} pool restarted"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def pool_log_name
|
|
55
|
+
if respond_to?(:name)
|
|
56
|
+
label = name.to_s
|
|
57
|
+
return label unless label.empty? || label.start_with?('#<')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
segments = if instance_variable_defined?(:@component_logger) && @component_logger.respond_to?(:segments)
|
|
61
|
+
Array(@component_logger.segments)
|
|
62
|
+
elsif log.respond_to?(:segments)
|
|
63
|
+
Array(log.segments)
|
|
64
|
+
else
|
|
65
|
+
[]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
segments.empty? ? 'cache.pool' : segments.join('.')
|
|
46
69
|
end
|
|
47
70
|
end
|
|
48
71
|
end
|
data/lib/legion/cache/redis.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'openssl'
|
|
4
4
|
require 'redis'
|
|
5
|
+
require 'legion/logging/helper'
|
|
5
6
|
require 'legion/cache/pool'
|
|
6
7
|
require 'legion/cache/settings'
|
|
7
8
|
|
|
@@ -10,14 +11,17 @@ module Legion
|
|
|
10
11
|
module Redis
|
|
11
12
|
include Legion::Cache::Pool
|
|
12
13
|
extend self
|
|
14
|
+
extend Legion::Logging::Helper
|
|
13
15
|
|
|
14
16
|
def client(pool_size: 20, timeout: 5, server: nil, servers: [], cluster: nil, replica: false, # rubocop:disable Metrics/ParameterLists
|
|
15
|
-
|
|
17
|
+
logger: nil,
|
|
18
|
+
fixed_hostname: nil, username: nil, password: nil, db: nil, reconnect_attempts: [0, 0.5, 1], **)
|
|
16
19
|
return @client unless @client.nil?
|
|
17
20
|
|
|
18
21
|
@pool_size = pool_size
|
|
19
22
|
@timeout = timeout
|
|
20
23
|
@cluster_mode = Array(cluster).compact.any?
|
|
24
|
+
@component_logger = logger || log
|
|
21
25
|
|
|
22
26
|
@client = ConnectionPool.new(size: pool_size, timeout: timeout) do
|
|
23
27
|
build_redis_client(server: server, servers: servers, cluster: cluster,
|
|
@@ -26,15 +30,20 @@ module Legion
|
|
|
26
30
|
reconnect_attempts: reconnect_attempts)
|
|
27
31
|
end
|
|
28
32
|
@connected = true
|
|
29
|
-
|
|
33
|
+
cache_logger.info "Redis connected to #{resolved_redis_address(server: server, servers: servers, cluster: cluster)}"
|
|
30
34
|
@client
|
|
35
|
+
rescue StandardError => e
|
|
36
|
+
handle_exception(e, level: :error, handled: false, operation: :redis_client,
|
|
37
|
+
server: server, servers: Array(servers), cluster_nodes: Array(cluster))
|
|
38
|
+
@connected = false
|
|
39
|
+
raise
|
|
31
40
|
end
|
|
32
41
|
|
|
33
42
|
def build_redis_client(server: nil, servers: [], cluster: nil, replica: false, fixed_hostname: nil, # rubocop:disable Metrics/ParameterLists
|
|
34
|
-
username: nil, password: nil, db: nil, reconnect_attempts: 1)
|
|
43
|
+
username: nil, password: nil, db: nil, reconnect_attempts: [0, 0.5, 1])
|
|
35
44
|
nodes = Array(cluster).compact
|
|
36
45
|
if nodes.any?
|
|
37
|
-
opts = { cluster: nodes, reconnect_attempts: reconnect_attempts }
|
|
46
|
+
opts = { cluster: nodes, reconnect_attempts: reconnect_attempts, timeout: @timeout }
|
|
38
47
|
opts[:replica] = true if replica
|
|
39
48
|
opts[:fixed_hostname] = fixed_hostname unless fixed_hostname.nil?
|
|
40
49
|
opts[:username] = username unless username.nil?
|
|
@@ -44,8 +53,9 @@ module Legion
|
|
|
44
53
|
resolved = Legion::Cache::Settings.resolve_servers(
|
|
45
54
|
driver: 'redis', server: server, servers: servers
|
|
46
55
|
)
|
|
47
|
-
host, port = resolved.first
|
|
48
|
-
redis_opts = { host: host, port: port.to_i, reconnect_attempts: reconnect_attempts
|
|
56
|
+
host, port = Legion::Cache::Settings.parse_server_address(resolved.first, default_port: 6379)
|
|
57
|
+
redis_opts = { host: host, port: port.to_i, reconnect_attempts: reconnect_attempts,
|
|
58
|
+
timeout: @timeout }
|
|
49
59
|
redis_opts[:username] = username unless username.nil?
|
|
50
60
|
redis_opts[:password] = password unless password.nil?
|
|
51
61
|
redis_opts[:db] = db unless db.nil?
|
|
@@ -60,31 +70,39 @@ module Legion
|
|
|
60
70
|
|
|
61
71
|
def get(key)
|
|
62
72
|
result = client.with { |conn| conn.get(key) }
|
|
63
|
-
|
|
73
|
+
cache_logger.debug "[cache] GET #{key} hit=#{!result.nil?}"
|
|
64
74
|
result
|
|
65
75
|
rescue ::Redis::BaseError => e
|
|
66
|
-
log_cluster_error(e)
|
|
76
|
+
log_cluster_error('redis_get', e, key: key)
|
|
67
77
|
raise
|
|
68
78
|
end
|
|
69
|
-
|
|
79
|
+
|
|
80
|
+
def fetch(key, ttl = nil)
|
|
81
|
+
result = get(key)
|
|
82
|
+
return result unless result.nil? && block_given?
|
|
83
|
+
|
|
84
|
+
result = yield
|
|
85
|
+
set(key, result, ttl)
|
|
86
|
+
result
|
|
87
|
+
end
|
|
70
88
|
|
|
71
89
|
def set(key, value, ttl = nil)
|
|
72
90
|
args = {}
|
|
73
91
|
args[:ex] = ttl unless ttl.nil?
|
|
74
92
|
result = client.with { |conn| conn.set(key, value, **args) == 'OK' }
|
|
75
|
-
|
|
93
|
+
cache_logger.debug "[cache] SET #{key} ttl=#{ttl.inspect} success=#{result}"
|
|
76
94
|
result
|
|
77
95
|
rescue ::Redis::BaseError => e
|
|
78
|
-
log_cluster_error(e)
|
|
96
|
+
log_cluster_error('redis_set', e, key: key, ttl: ttl)
|
|
79
97
|
raise
|
|
80
98
|
end
|
|
81
99
|
|
|
82
100
|
def delete(key)
|
|
83
101
|
result = client.with { |conn| conn.del(key) == 1 }
|
|
84
|
-
|
|
102
|
+
cache_logger.debug "[cache] DELETE #{key} success=#{result}"
|
|
85
103
|
result
|
|
86
104
|
rescue ::Redis::BaseError => e
|
|
87
|
-
log_cluster_error(e)
|
|
105
|
+
log_cluster_error('redis_delete', e, key: key)
|
|
88
106
|
raise
|
|
89
107
|
end
|
|
90
108
|
|
|
@@ -96,10 +114,10 @@ module Legion
|
|
|
96
114
|
conn.flushdb == 'OK'
|
|
97
115
|
end
|
|
98
116
|
end
|
|
99
|
-
|
|
117
|
+
cache_logger.debug '[cache] FLUSH completed'
|
|
100
118
|
result
|
|
101
119
|
rescue ::Redis::BaseError => e
|
|
102
|
-
log_cluster_error(e)
|
|
120
|
+
log_cluster_error('redis_flush', e)
|
|
103
121
|
raise
|
|
104
122
|
end
|
|
105
123
|
|
|
@@ -115,10 +133,10 @@ module Legion
|
|
|
115
133
|
keys.zip(values).to_h
|
|
116
134
|
end
|
|
117
135
|
end
|
|
118
|
-
|
|
136
|
+
cache_logger.debug "[cache] MGET keys=#{keys.size}"
|
|
119
137
|
result
|
|
120
138
|
rescue ::Redis::BaseError => e
|
|
121
|
-
log_cluster_error(e)
|
|
139
|
+
log_cluster_error('redis_mget', e, key_count: keys.size)
|
|
122
140
|
raise
|
|
123
141
|
end
|
|
124
142
|
|
|
@@ -132,15 +150,19 @@ module Legion
|
|
|
132
150
|
conn.mset(*hash.flatten) == 'OK'
|
|
133
151
|
end
|
|
134
152
|
end
|
|
135
|
-
|
|
153
|
+
cache_logger.debug "[cache] MSET keys=#{hash.size}"
|
|
136
154
|
result
|
|
137
155
|
rescue ::Redis::BaseError => e
|
|
138
|
-
log_cluster_error(e)
|
|
156
|
+
log_cluster_error('redis_mset', e, key_count: hash.size)
|
|
139
157
|
raise
|
|
140
158
|
end
|
|
141
159
|
|
|
142
160
|
private
|
|
143
161
|
|
|
162
|
+
def cache_logger
|
|
163
|
+
@component_logger || log
|
|
164
|
+
end
|
|
165
|
+
|
|
144
166
|
def cluster_mget(conn, keys)
|
|
145
167
|
groups = group_keys_by_slot(keys)
|
|
146
168
|
result = {}
|
|
@@ -164,14 +186,14 @@ module Legion
|
|
|
164
186
|
node_info = conn.cluster('nodes')
|
|
165
187
|
primaries = node_info.lines.select { |l| l.include?('master') }.map { |l| l.split[1].split('@').first }
|
|
166
188
|
primaries.each do |addr|
|
|
167
|
-
host, port =
|
|
189
|
+
host, port = Legion::Cache::Settings.parse_server_address(addr, default_port: 6379)
|
|
168
190
|
node = ::Redis.new(host: host, port: port.to_i)
|
|
169
191
|
node.flushdb
|
|
170
192
|
node.close
|
|
171
193
|
end
|
|
172
194
|
true
|
|
173
195
|
rescue StandardError => e
|
|
174
|
-
|
|
196
|
+
handle_exception(e, level: :warn, handled: true, operation: :cluster_flush, fallback: :single_flushdb)
|
|
175
197
|
conn.flushdb == 'OK'
|
|
176
198
|
end
|
|
177
199
|
|
|
@@ -189,14 +211,12 @@ module Legion
|
|
|
189
211
|
|
|
190
212
|
Legion::Cache::Settings.resolve_servers(driver: 'redis', server: server, servers: Array(servers)).first
|
|
191
213
|
rescue StandardError => e
|
|
192
|
-
|
|
214
|
+
handle_exception(e, level: :warn, handled: true, operation: :resolved_redis_address)
|
|
193
215
|
'unknown'
|
|
194
216
|
end
|
|
195
217
|
|
|
196
|
-
def log_cluster_error(error)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
Legion::Logging.warn "Redis cluster error: #{error.class} — #{error.message}"
|
|
218
|
+
def log_cluster_error(operation, error, **)
|
|
219
|
+
handle_exception(error, level: :warn, handled: false, operation: operation, **)
|
|
200
220
|
end
|
|
201
221
|
|
|
202
222
|
def redis_tls_options(port:)
|
|
@@ -218,7 +238,7 @@ module Legion
|
|
|
218
238
|
|
|
219
239
|
Legion::Settings[:cache][:tls] || {}
|
|
220
240
|
rescue StandardError => e
|
|
221
|
-
|
|
241
|
+
handle_exception(e, level: :warn, handled: true, operation: :cache_tls_settings)
|
|
222
242
|
{}
|
|
223
243
|
end
|
|
224
244
|
end
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'legion/logging/helper'
|
|
4
|
+
|
|
3
5
|
module Legion
|
|
4
6
|
module Cache
|
|
5
7
|
module RedisHash
|
|
8
|
+
extend Legion::Logging::Helper
|
|
9
|
+
|
|
6
10
|
module_function
|
|
7
11
|
|
|
8
12
|
# Returns true when the Redis driver is loaded and the connection pool is live.
|
|
9
13
|
def redis_available?
|
|
10
14
|
pool = Legion::Cache.instance_variable_get(:@client)
|
|
11
15
|
return false if pool.nil?
|
|
16
|
+
return false unless Legion::Cache.respond_to?(:driver_name) && Legion::Cache.driver_name == 'redis'
|
|
12
17
|
|
|
13
18
|
Legion::Cache.connected?
|
|
14
|
-
rescue StandardError
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
handle_exception(e, level: :warn, handled: true, operation: :redis_hash_available)
|
|
15
21
|
false
|
|
16
22
|
end
|
|
17
23
|
|
|
@@ -24,6 +30,7 @@ module Legion
|
|
|
24
30
|
flat = hash.flat_map { |k, v| [k.to_s, v.to_s] }
|
|
25
31
|
conn.hset(key, *flat)
|
|
26
32
|
end
|
|
33
|
+
log.debug "[cache:redis_hash] HSET #{key} fields=#{hash.size}"
|
|
27
34
|
true
|
|
28
35
|
rescue StandardError => e
|
|
29
36
|
log_redis_error('hset', e)
|
|
@@ -34,9 +41,11 @@ module Legion
|
|
|
34
41
|
def hgetall(key)
|
|
35
42
|
return nil unless redis_available?
|
|
36
43
|
|
|
37
|
-
Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
44
|
+
result = Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
38
45
|
conn.hgetall(key)
|
|
39
46
|
end
|
|
47
|
+
log.debug "[cache:redis_hash] HGETALL #{key} fields=#{result.size}"
|
|
48
|
+
result
|
|
40
49
|
rescue StandardError => e
|
|
41
50
|
log_redis_error('hgetall', e)
|
|
42
51
|
nil
|
|
@@ -46,9 +55,11 @@ module Legion
|
|
|
46
55
|
def hdel(key, *fields)
|
|
47
56
|
return 0 unless redis_available?
|
|
48
57
|
|
|
49
|
-
Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
58
|
+
result = Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
50
59
|
conn.hdel(key, *fields)
|
|
51
60
|
end
|
|
61
|
+
log.debug "[cache:redis_hash] HDEL #{key} fields=#{fields.size} removed=#{result}"
|
|
62
|
+
result
|
|
52
63
|
rescue StandardError => e
|
|
53
64
|
log_redis_error('hdel', e)
|
|
54
65
|
0
|
|
@@ -61,6 +72,7 @@ module Legion
|
|
|
61
72
|
Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
62
73
|
conn.zadd(key, score.to_f, member.to_s)
|
|
63
74
|
end
|
|
75
|
+
log.debug "[cache:redis_hash] ZADD #{key} member=#{member}"
|
|
64
76
|
true
|
|
65
77
|
rescue StandardError => e
|
|
66
78
|
log_redis_error('zadd', e)
|
|
@@ -75,9 +87,11 @@ module Legion
|
|
|
75
87
|
opts = {}
|
|
76
88
|
opts[:limit] = limit if limit
|
|
77
89
|
|
|
78
|
-
Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
90
|
+
result = Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
79
91
|
conn.zrangebyscore(key, min, max, **opts)
|
|
80
92
|
end
|
|
93
|
+
log.debug "[cache:redis_hash] ZRANGEBYSCORE #{key} results=#{result.size}"
|
|
94
|
+
result
|
|
81
95
|
rescue StandardError => e
|
|
82
96
|
log_redis_error('zrangebyscore', e)
|
|
83
97
|
[]
|
|
@@ -90,6 +104,7 @@ module Legion
|
|
|
90
104
|
Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
91
105
|
conn.zrem(key, member.to_s)
|
|
92
106
|
end
|
|
107
|
+
log.debug "[cache:redis_hash] ZREM #{key} member=#{member}"
|
|
93
108
|
true
|
|
94
109
|
rescue StandardError => e
|
|
95
110
|
log_redis_error('zrem', e)
|
|
@@ -100,18 +115,18 @@ module Legion
|
|
|
100
115
|
def expire(key, seconds)
|
|
101
116
|
return false unless redis_available?
|
|
102
117
|
|
|
103
|
-
Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
118
|
+
result = Legion::Cache.instance_variable_get(:@client).with do |conn|
|
|
104
119
|
conn.expire(key, seconds.to_i) == 1
|
|
105
120
|
end
|
|
121
|
+
log.debug "[cache:redis_hash] EXPIRE #{key} seconds=#{seconds} success=#{result}"
|
|
122
|
+
result
|
|
106
123
|
rescue StandardError => e
|
|
107
124
|
log_redis_error('expire', e)
|
|
108
125
|
false
|
|
109
126
|
end
|
|
110
127
|
|
|
111
128
|
def log_redis_error(method, error)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
Legion::Logging.warn "[cache:redis_hash] #{method} failed: #{error.class} — #{error.message}"
|
|
129
|
+
handle_exception(error, level: :warn, handled: true, operation: method)
|
|
115
130
|
end
|
|
116
131
|
end
|
|
117
132
|
end
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
rescue StandardError => e
|
|
6
|
-
warn "legion-cache: failed to require legion/settings: #{e.message}"
|
|
7
|
-
end
|
|
3
|
+
require 'ipaddr'
|
|
4
|
+
require 'legion/logging/helper'
|
|
8
5
|
|
|
9
6
|
module Legion
|
|
10
7
|
module Cache
|
|
11
8
|
module Settings
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
extend Legion::Logging::Helper
|
|
10
|
+
|
|
11
|
+
begin
|
|
12
|
+
require 'legion/settings'
|
|
13
|
+
rescue StandardError => e
|
|
14
|
+
handle_exception(e,
|
|
15
|
+
level: :error,
|
|
16
|
+
handled: true,
|
|
17
|
+
operation: :cache_settings_require_legion_settings)
|
|
18
|
+
end
|
|
19
|
+
|
|
14
20
|
def self.default
|
|
15
21
|
{
|
|
16
22
|
driver: driver,
|
|
@@ -33,7 +39,7 @@ module Legion
|
|
|
33
39
|
username: nil,
|
|
34
40
|
password: nil,
|
|
35
41
|
db: nil,
|
|
36
|
-
reconnect_attempts: 1
|
|
42
|
+
reconnect_attempts: [0, 0.5, 1].freeze
|
|
37
43
|
}
|
|
38
44
|
end
|
|
39
45
|
|
|
@@ -56,7 +62,7 @@ module Legion
|
|
|
56
62
|
username: nil,
|
|
57
63
|
password: nil,
|
|
58
64
|
db: nil,
|
|
59
|
-
reconnect_attempts:
|
|
65
|
+
reconnect_attempts: [0, 0.25, 0.5].freeze
|
|
60
66
|
}
|
|
61
67
|
end
|
|
62
68
|
|
|
@@ -69,8 +75,34 @@ module Legion
|
|
|
69
75
|
all = Array(servers) + Array(server)
|
|
70
76
|
all = ["127.0.0.1:#{port}"] if all.empty?
|
|
71
77
|
|
|
72
|
-
all.map! { |s|
|
|
73
|
-
all.uniq
|
|
78
|
+
all.map! { |s| normalize_server(s, port: port) }
|
|
79
|
+
resolved = all.uniq
|
|
80
|
+
log.debug "Legion::Cache::Settings resolved driver=#{gem_driver} servers=#{resolved.join(', ')}"
|
|
81
|
+
resolved
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self.parse_server_address(server, default_port:)
|
|
85
|
+
raw = server.to_s.strip
|
|
86
|
+
return ['127.0.0.1', default_port] if raw.empty?
|
|
87
|
+
|
|
88
|
+
bracketed = raw.match(/\A\[(?<host>[^\]]+)\](?::(?<port>\d+))?\z/)
|
|
89
|
+
return [bracketed[:host], (bracketed[:port] || default_port).to_i] if bracketed
|
|
90
|
+
|
|
91
|
+
return [raw, default_port] if ipv6_literal?(raw)
|
|
92
|
+
|
|
93
|
+
host, explicit_port = raw.split(':', 2)
|
|
94
|
+
if explicit_port&.match?(/\A\d+\z/)
|
|
95
|
+
[host, explicit_port.to_i]
|
|
96
|
+
else
|
|
97
|
+
[raw, default_port]
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def self.register_defaults!
|
|
102
|
+
return unless defined?(Legion::Settings) && Legion::Settings.respond_to?(:merge_settings)
|
|
103
|
+
|
|
104
|
+
Legion::Settings.merge_settings(:cache, default)
|
|
105
|
+
Legion::Settings.merge_settings(:cache_local, local)
|
|
74
106
|
end
|
|
75
107
|
|
|
76
108
|
def self.normalize_driver(name)
|
|
@@ -84,13 +116,36 @@ module Legion
|
|
|
84
116
|
def self.driver(prefer = 'dalli')
|
|
85
117
|
secondary = prefer == 'dalli' ? 'redis' : 'dalli'
|
|
86
118
|
if Gem::Specification.find_all_by_name(prefer).any?
|
|
119
|
+
log.debug "Legion::Cache::Settings selected driver=#{prefer}"
|
|
87
120
|
prefer
|
|
88
121
|
elsif Gem::Specification.find_all_by_name(secondary).any?
|
|
122
|
+
log.info "Legion::Cache::Settings falling back driver=#{secondary} preferred=#{prefer}"
|
|
89
123
|
secondary
|
|
90
124
|
else
|
|
91
|
-
|
|
125
|
+
error = NameError.new('Legion::Cache.driver is nil')
|
|
126
|
+
handle_exception(error, level: :error, handled: false, operation: :cache_settings_driver, preferred: prefer)
|
|
127
|
+
raise error
|
|
92
128
|
end
|
|
93
129
|
end
|
|
130
|
+
|
|
131
|
+
def self.normalize_server(server, port:)
|
|
132
|
+
host, resolved_port = parse_server_address(server, default_port: port)
|
|
133
|
+
format_server(host, resolved_port)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def self.format_server(host, port)
|
|
137
|
+
return "[#{host}]:#{port}" if ipv6_literal?(host)
|
|
138
|
+
|
|
139
|
+
"#{host}:#{port}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def self.ipv6_literal?(value)
|
|
143
|
+
IPAddr.new(value).ipv6?
|
|
144
|
+
rescue IPAddr::InvalidAddressError
|
|
145
|
+
false
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
register_defaults!
|
|
94
149
|
end
|
|
95
150
|
end
|
|
96
151
|
end
|