legion-cache 1.3.22 → 1.4.2
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 +55 -0
- data/legion-cache.gemspec +1 -0
- data/lib/legion/cache/async_writer.rb +126 -0
- data/lib/legion/cache/cacheable.rb +4 -4
- data/lib/legion/cache/helper.rb +11 -11
- data/lib/legion/cache/local.rb +91 -29
- data/lib/legion/cache/memcached.rb +62 -39
- data/lib/legion/cache/memory.rb +126 -19
- data/lib/legion/cache/pool.rb +4 -1
- data/lib/legion/cache/reconnector.rb +108 -0
- data/lib/legion/cache/redis.rb +119 -47
- data/lib/legion/cache/redis_hash.rb +8 -8
- data/lib/legion/cache/settings.rb +52 -39
- data/lib/legion/cache/version.rb +1 -1
- data/lib/legion/cache.rb +323 -70
- metadata +17 -1
|
@@ -12,34 +12,38 @@ module Legion
|
|
|
12
12
|
extend self
|
|
13
13
|
extend Legion::Logging::Helper
|
|
14
14
|
|
|
15
|
-
def client(server: nil, servers: nil,
|
|
15
|
+
def client(server: nil, servers: nil, pool_size: nil, timeout: nil, # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/ParameterLists
|
|
16
|
+
username: nil, password: nil, logger: nil, **opts)
|
|
16
17
|
return @client unless @client.nil?
|
|
17
18
|
|
|
18
19
|
settings = defined?(Legion::Settings) ? Legion::Settings[:cache] : {}
|
|
19
20
|
servers ||= settings[:servers] || []
|
|
20
21
|
@component_logger = logger || log
|
|
21
22
|
|
|
22
|
-
@pool_size =
|
|
23
|
-
@timeout =
|
|
23
|
+
@pool_size = pool_size || settings[:pool_size] || 10
|
|
24
|
+
@timeout = timeout || settings[:timeout] || 5
|
|
24
25
|
|
|
25
26
|
resolved = Legion::Cache::Settings.resolve_servers(
|
|
26
27
|
driver: 'memcached', server: server, servers: Array(servers)
|
|
27
28
|
)
|
|
28
29
|
|
|
29
|
-
Dalli.logger =
|
|
30
|
+
Dalli.logger = log
|
|
30
31
|
cache_opts = settings.merge(opts)
|
|
31
32
|
cache_opts[:value_max_bytes] ||= 8 * 1024 * 1024
|
|
32
33
|
cache_opts[:serializer] ||= Legion::JSON
|
|
34
|
+
cache_opts[:username] = username unless username.nil?
|
|
35
|
+
cache_opts[:password] = password unless password.nil?
|
|
33
36
|
|
|
34
37
|
tls_ctx = memcached_tls_context(port: resolved.first.split(':').last.to_i)
|
|
35
38
|
cache_opts[:ssl_context] = tls_ctx if tls_ctx
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
checkout_timeout = opts[:pool_checkout_timeout] || settings[:pool_checkout_timeout] || @timeout
|
|
41
|
+
@client = ConnectionPool.new(size: @pool_size, timeout: checkout_timeout) do
|
|
38
42
|
Dalli::Client.new(resolved, cache_opts)
|
|
39
43
|
end
|
|
40
44
|
|
|
41
45
|
@connected = true
|
|
42
|
-
|
|
46
|
+
log.info "Memcached connected to #{resolved.join(', ')}"
|
|
43
47
|
@client
|
|
44
48
|
rescue StandardError => e
|
|
45
49
|
handle_exception(e, level: :error, handled: false, operation: :memcached_client,
|
|
@@ -50,14 +54,14 @@ module Legion
|
|
|
50
54
|
|
|
51
55
|
def get(key)
|
|
52
56
|
result = client.with { |conn| conn.get(key) }
|
|
53
|
-
|
|
57
|
+
log.debug { "[cache] GET #{key} hit=#{!result.nil?}" }
|
|
54
58
|
result
|
|
55
59
|
rescue StandardError => e
|
|
56
|
-
handle_exception(e, level: :warn, handled:
|
|
57
|
-
|
|
60
|
+
handle_exception(e, level: :warn, handled: true, operation: :memcached_get, key: key)
|
|
61
|
+
nil
|
|
58
62
|
end
|
|
59
63
|
|
|
60
|
-
def fetch(key, ttl
|
|
64
|
+
def fetch(key, ttl: nil, &)
|
|
61
65
|
result = client.with do |conn|
|
|
62
66
|
if block_given?
|
|
63
67
|
conn.fetch(key, ttl, &)
|
|
@@ -65,38 +69,57 @@ module Legion
|
|
|
65
69
|
conn.fetch(key, ttl)
|
|
66
70
|
end
|
|
67
71
|
end
|
|
68
|
-
|
|
72
|
+
log.debug { "[cache] FETCH #{key} hit=#{!result.nil?}" }
|
|
73
|
+
result
|
|
74
|
+
rescue StandardError => e
|
|
75
|
+
handle_exception(e, level: :warn, handled: true, operation: :memcached_fetch, key: key, ttl: ttl)
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def set_nx(key, value, ttl: nil)
|
|
80
|
+
effective_ttl = ttl || default_ttl
|
|
81
|
+
result = client.with { |conn| conn.add(key, value, effective_ttl) == true }
|
|
82
|
+
log.debug { "[cache] SET_NX #{key} ttl=#{effective_ttl.inspect} result=#{result}" }
|
|
69
83
|
result
|
|
70
84
|
rescue StandardError => e
|
|
71
|
-
handle_exception(e, level: :
|
|
85
|
+
handle_exception(e, level: :error, handled: false, operation: :memcached_set_nx, key: key, ttl: effective_ttl)
|
|
72
86
|
raise
|
|
73
87
|
end
|
|
74
88
|
|
|
75
|
-
def set(key, value, ttl
|
|
76
|
-
|
|
77
|
-
|
|
89
|
+
def set(key, value, ttl: nil, **)
|
|
90
|
+
set_sync(key, value, ttl: ttl, **)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def set_sync(key, value, ttl: nil, **)
|
|
94
|
+
effective_ttl = ttl || default_ttl
|
|
95
|
+
result = client.with { |conn| conn.set(key, value, effective_ttl).positive? }
|
|
96
|
+
log.debug { "[cache] SET #{key} ttl=#{effective_ttl} success=#{result} value_class=#{value.class}" }
|
|
78
97
|
result
|
|
79
98
|
rescue StandardError => e
|
|
80
|
-
handle_exception(e, level: :
|
|
99
|
+
handle_exception(e, level: :error, handled: false, operation: :memcached_set_sync, key: key, ttl: effective_ttl)
|
|
81
100
|
raise
|
|
82
101
|
end
|
|
83
102
|
|
|
84
|
-
def delete(key)
|
|
103
|
+
def delete(key, **)
|
|
104
|
+
delete_sync(key)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def delete_sync(key)
|
|
85
108
|
result = client.with { |conn| conn.delete(key) == true }
|
|
86
|
-
|
|
109
|
+
log.debug { "[cache] DELETE #{key} success=#{result}" }
|
|
87
110
|
result
|
|
88
111
|
rescue StandardError => e
|
|
89
|
-
handle_exception(e, level: :
|
|
112
|
+
handle_exception(e, level: :error, handled: false, operation: :memcached_delete_sync, key: key)
|
|
90
113
|
raise
|
|
91
114
|
end
|
|
92
115
|
|
|
93
|
-
def flush
|
|
94
|
-
result = client.with { |conn| conn.flush
|
|
95
|
-
|
|
116
|
+
def flush
|
|
117
|
+
result = client.with { |conn| conn.flush.first }
|
|
118
|
+
log.debug { '[cache] FLUSH completed' }
|
|
96
119
|
result
|
|
97
120
|
rescue StandardError => e
|
|
98
|
-
handle_exception(e, level: :warn, handled:
|
|
99
|
-
|
|
121
|
+
handle_exception(e, level: :warn, handled: true, operation: :memcached_flush)
|
|
122
|
+
nil
|
|
100
123
|
end
|
|
101
124
|
|
|
102
125
|
def mget(*keys)
|
|
@@ -104,36 +127,36 @@ module Legion
|
|
|
104
127
|
return {} if keys.empty?
|
|
105
128
|
|
|
106
129
|
result = client.with { |conn| conn.get_multi(*keys) }
|
|
107
|
-
|
|
130
|
+
log.debug { "[cache] MGET keys=#{keys.size} hits=#{result.size}" }
|
|
108
131
|
result
|
|
109
132
|
rescue StandardError => e
|
|
110
|
-
handle_exception(e, level: :warn, handled:
|
|
111
|
-
|
|
133
|
+
handle_exception(e, level: :warn, handled: true, operation: :memcached_mget, key_count: keys.size)
|
|
134
|
+
{}
|
|
112
135
|
end
|
|
113
136
|
|
|
114
|
-
def mset(hash)
|
|
137
|
+
def mset(hash, ttl: nil, **)
|
|
138
|
+
mset_sync(hash, ttl: ttl)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def mset_sync(hash, ttl: nil, **) # rubocop:disable Lint/UnusedMethodArgument
|
|
115
142
|
return true if hash.empty?
|
|
116
143
|
|
|
117
144
|
client.with { |conn| conn.set_multi(hash) }
|
|
118
|
-
|
|
145
|
+
log.debug { "[cache] MSET keys=#{hash.size}" }
|
|
119
146
|
true
|
|
120
147
|
rescue StandardError => e
|
|
121
|
-
handle_exception(e, level: :
|
|
148
|
+
handle_exception(e, level: :error, handled: false, operation: :memcached_mset_sync, key_count: hash.size)
|
|
122
149
|
raise
|
|
123
150
|
end
|
|
124
151
|
|
|
125
152
|
private
|
|
126
153
|
|
|
127
|
-
def
|
|
128
|
-
|
|
129
|
-
end
|
|
154
|
+
def default_ttl
|
|
155
|
+
return 3600 unless defined?(Legion::Settings)
|
|
130
156
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
else
|
|
135
|
-
cache_logger
|
|
136
|
-
end
|
|
157
|
+
Legion::Settings.dig(:cache, :default_ttl) || 3600
|
|
158
|
+
rescue StandardError
|
|
159
|
+
3600
|
|
137
160
|
end
|
|
138
161
|
|
|
139
162
|
def memcached_tls_context(port:)
|
data/lib/legion/cache/memory.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'concurrent'
|
|
3
4
|
require 'legion/logging/helper'
|
|
4
5
|
|
|
5
6
|
module Legion
|
|
@@ -11,18 +12,31 @@ module Legion
|
|
|
11
12
|
@store = {}
|
|
12
13
|
@expiry = {}
|
|
13
14
|
@mutex = Mutex.new
|
|
14
|
-
@connected = false
|
|
15
|
+
@connected = Concurrent::AtomicBoolean.new(false)
|
|
15
16
|
|
|
16
17
|
def setup(**)
|
|
17
|
-
@connected
|
|
18
|
+
@connected.make_true
|
|
18
19
|
log.info 'Legion::Cache::Memory connected'
|
|
19
|
-
|
|
20
|
+
true
|
|
21
|
+
rescue StandardError => e
|
|
22
|
+
@connected.make_false
|
|
23
|
+
handle_exception(e, level: :warn, handled: true, operation: :memory_setup)
|
|
24
|
+
false
|
|
20
25
|
end
|
|
21
26
|
|
|
22
27
|
def client(**) = self
|
|
23
28
|
|
|
24
29
|
def connected?
|
|
25
|
-
@connected
|
|
30
|
+
@connected.true?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def restart(**)
|
|
34
|
+
shutdown
|
|
35
|
+
setup
|
|
36
|
+
rescue StandardError => e
|
|
37
|
+
@connected.make_false
|
|
38
|
+
handle_exception(e, level: :warn, handled: true, operation: :memory_restart)
|
|
39
|
+
false
|
|
26
40
|
end
|
|
27
41
|
|
|
28
42
|
def get(key)
|
|
@@ -32,9 +46,36 @@ module Legion
|
|
|
32
46
|
log.debug { "[cache:memory] GET #{key} hit=#{!result.nil?}" }
|
|
33
47
|
result
|
|
34
48
|
end
|
|
49
|
+
rescue StandardError => e
|
|
50
|
+
handle_exception(e, level: :warn, handled: true, operation: :memory_get)
|
|
51
|
+
nil
|
|
35
52
|
end
|
|
36
53
|
|
|
37
|
-
def set(key, value, ttl
|
|
54
|
+
def set(key, value, ttl: nil, async: true, phi: false) # rubocop:disable Lint/UnusedMethodArgument
|
|
55
|
+
set_sync(key, value, ttl: ttl, phi: phi)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def set_nx(key, value, ttl: nil)
|
|
59
|
+
@mutex.synchronize do
|
|
60
|
+
expire_if_needed(key)
|
|
61
|
+
return false if @store.key?(key)
|
|
62
|
+
|
|
63
|
+
@store[key] = value
|
|
64
|
+
if ttl&.positive?
|
|
65
|
+
@expiry[key] = Time.now + ttl
|
|
66
|
+
else
|
|
67
|
+
@expiry.delete(key)
|
|
68
|
+
end
|
|
69
|
+
log.debug { "[cache:memory] SET_NX #{key} ttl=#{ttl.inspect} result=true" }
|
|
70
|
+
true
|
|
71
|
+
end
|
|
72
|
+
rescue StandardError => e
|
|
73
|
+
handle_exception(e, level: :warn, handled: true, operation: :memory_set_nx)
|
|
74
|
+
false
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def set_sync(key, value, ttl: nil, phi: false)
|
|
78
|
+
ttl = enforce_phi_ttl(ttl, phi: phi) if phi
|
|
38
79
|
@mutex.synchronize do
|
|
39
80
|
@store[key] = value
|
|
40
81
|
if ttl&.positive?
|
|
@@ -43,55 +84,109 @@ module Legion
|
|
|
43
84
|
@expiry.delete(key)
|
|
44
85
|
end
|
|
45
86
|
log.debug { "[cache:memory] SET #{key} ttl=#{ttl.inspect}" }
|
|
46
|
-
|
|
87
|
+
true
|
|
47
88
|
end
|
|
48
89
|
end
|
|
49
90
|
|
|
50
|
-
def fetch(key, ttl
|
|
91
|
+
def fetch(key, ttl: nil, &block)
|
|
51
92
|
val = get(key)
|
|
52
93
|
return val unless val.nil?
|
|
53
94
|
|
|
54
95
|
log.debug { "[cache:memory] FETCH #{key} miss=true" }
|
|
55
|
-
val =
|
|
56
|
-
set(key, val, ttl)
|
|
96
|
+
val = block&.call
|
|
97
|
+
set(key, val, ttl: ttl)
|
|
57
98
|
val
|
|
99
|
+
rescue StandardError => e
|
|
100
|
+
handle_exception(e, level: :warn, handled: true, operation: :memory_fetch)
|
|
101
|
+
nil
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def delete(key, async: true) # rubocop:disable Lint/UnusedMethodArgument
|
|
105
|
+
delete_sync(key)
|
|
58
106
|
end
|
|
59
107
|
|
|
60
|
-
def
|
|
108
|
+
def delete_sync(key)
|
|
61
109
|
@mutex.synchronize do
|
|
62
110
|
removed = @store.delete(key)
|
|
63
111
|
@expiry.delete(key)
|
|
64
112
|
log.debug { "[cache:memory] DELETE #{key} success=#{!removed.nil?}" }
|
|
65
|
-
removed
|
|
113
|
+
!removed.nil?
|
|
66
114
|
end
|
|
67
115
|
end
|
|
68
116
|
|
|
69
|
-
def
|
|
70
|
-
|
|
117
|
+
def mget(*keys)
|
|
118
|
+
keys = keys.flatten
|
|
119
|
+
return {} if keys.empty?
|
|
120
|
+
|
|
121
|
+
@mutex.synchronize do
|
|
122
|
+
keys.each { |k| expire_if_needed(k) }
|
|
123
|
+
keys.to_h { |k| [k, @store[k]] }
|
|
124
|
+
end
|
|
125
|
+
rescue StandardError => e
|
|
126
|
+
handle_exception(e, level: :warn, handled: true, operation: :memory_mget)
|
|
127
|
+
{}
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def mset(hash, ttl: nil, async: true)
|
|
131
|
+
return true if hash.empty?
|
|
132
|
+
|
|
133
|
+
hash.each { |k, v| set(k, v, ttl: ttl, async: async) }
|
|
134
|
+
true
|
|
135
|
+
rescue StandardError => e
|
|
136
|
+
handle_exception(e, level: :warn, handled: true, operation: :memory_mset)
|
|
137
|
+
true
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def mset_sync(hash, ttl: nil, phi: false)
|
|
141
|
+
return true if hash.empty?
|
|
142
|
+
|
|
143
|
+
@mutex.synchronize do
|
|
144
|
+
hash.each do |key, value|
|
|
145
|
+
effective_ttl = phi ? enforce_phi_ttl(ttl, phi: true) : ttl
|
|
146
|
+
@store[key] = value
|
|
147
|
+
if effective_ttl&.positive?
|
|
148
|
+
@expiry[key] = Time.now + effective_ttl
|
|
149
|
+
else
|
|
150
|
+
@expiry.delete(key)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
true
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def flush
|
|
158
|
+
@mutex.synchronize do
|
|
71
159
|
@store.clear
|
|
72
160
|
@expiry.clear
|
|
73
161
|
end
|
|
74
162
|
log.info 'Legion::Cache::Memory flushed'
|
|
75
|
-
|
|
163
|
+
true
|
|
164
|
+
rescue StandardError => e
|
|
165
|
+
handle_exception(e, level: :warn, handled: true, operation: :memory_flush)
|
|
166
|
+
false
|
|
76
167
|
end
|
|
77
168
|
|
|
78
169
|
def close = nil
|
|
79
170
|
|
|
80
171
|
def shutdown
|
|
81
172
|
flush
|
|
82
|
-
@connected
|
|
173
|
+
@connected.make_false
|
|
83
174
|
log.info 'Legion::Cache::Memory shut down'
|
|
84
|
-
|
|
175
|
+
false
|
|
176
|
+
rescue StandardError => e
|
|
177
|
+
@connected.make_false
|
|
178
|
+
handle_exception(e, level: :warn, handled: true, operation: :memory_shutdown)
|
|
179
|
+
false
|
|
85
180
|
end
|
|
86
181
|
|
|
87
182
|
def reset!
|
|
88
|
-
|
|
183
|
+
@mutex.synchronize do
|
|
184
|
+
@connected.make_false
|
|
89
185
|
@store.clear
|
|
90
186
|
@expiry.clear
|
|
91
|
-
@connected = false
|
|
92
187
|
end
|
|
93
188
|
log.info 'Legion::Cache::Memory state reset'
|
|
94
|
-
|
|
189
|
+
false
|
|
95
190
|
end
|
|
96
191
|
|
|
97
192
|
def size = 1
|
|
@@ -106,6 +201,18 @@ module Legion
|
|
|
106
201
|
@expiry.delete(key)
|
|
107
202
|
log.debug { "[cache:memory] EXPIRE #{key}" }
|
|
108
203
|
end
|
|
204
|
+
|
|
205
|
+
def enforce_phi_ttl(ttl, phi: false)
|
|
206
|
+
return ttl unless phi
|
|
207
|
+
|
|
208
|
+
max = if defined?(Legion::Settings)
|
|
209
|
+
Legion::Settings.dig(:cache, :compliance, :phi_max_ttl) || 3600
|
|
210
|
+
else
|
|
211
|
+
3600
|
|
212
|
+
end
|
|
213
|
+
result = ttl.nil? ? max : [ttl, max].min
|
|
214
|
+
[result, 1].max
|
|
215
|
+
end
|
|
109
216
|
end
|
|
110
217
|
end
|
|
111
218
|
end
|
data/lib/legion/cache/pool.rb
CHANGED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'concurrent'
|
|
4
|
+
require 'legion/logging/helper'
|
|
5
|
+
|
|
6
|
+
module Legion
|
|
7
|
+
module Cache
|
|
8
|
+
class Reconnector
|
|
9
|
+
include Legion::Logging::Helper
|
|
10
|
+
|
|
11
|
+
DEFAULT_INITIAL_DELAY = 1
|
|
12
|
+
DEFAULT_MAX_DELAY = 60
|
|
13
|
+
|
|
14
|
+
def initialize(tier:, connect_block:, enabled_block:, settings_key: :cache)
|
|
15
|
+
@tier = tier
|
|
16
|
+
@connect_block = connect_block
|
|
17
|
+
@enabled_block = enabled_block
|
|
18
|
+
@settings_key = settings_key
|
|
19
|
+
@attempts = Concurrent::AtomicFixnum.new(0)
|
|
20
|
+
@thread = nil
|
|
21
|
+
@mutex = Mutex.new
|
|
22
|
+
@stop_signal = Concurrent::AtomicBoolean.new(false)
|
|
23
|
+
@next_retry_at = nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def start
|
|
27
|
+
@mutex.synchronize do
|
|
28
|
+
return if running?
|
|
29
|
+
|
|
30
|
+
@stop_signal.make_false
|
|
31
|
+
@thread = Thread.new { reconnect_loop }
|
|
32
|
+
log.info "Legion::Cache::Reconnector[#{@tier}] started"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def stop
|
|
37
|
+
thread_to_join = nil
|
|
38
|
+
@mutex.synchronize do
|
|
39
|
+
@stop_signal.make_true
|
|
40
|
+
thread_to_join = @thread
|
|
41
|
+
@thread = nil
|
|
42
|
+
end
|
|
43
|
+
thread_to_join&.join(5)
|
|
44
|
+
log.info "Legion::Cache::Reconnector[#{@tier}] stopped"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def running?
|
|
48
|
+
@thread&.alive? == true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def attempts
|
|
52
|
+
@attempts.value
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
attr_reader :next_retry_at
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def reconnect_loop
|
|
60
|
+
delay = configured_initial_delay
|
|
61
|
+
|
|
62
|
+
until @stop_signal.true?
|
|
63
|
+
unless @enabled_block.call
|
|
64
|
+
sleep 1
|
|
65
|
+
next
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
begin
|
|
69
|
+
@next_retry_at = Time.now + delay
|
|
70
|
+
sleep delay
|
|
71
|
+
return if @stop_signal.true?
|
|
72
|
+
|
|
73
|
+
@connect_block.call
|
|
74
|
+
count = @attempts.value
|
|
75
|
+
@attempts = Concurrent::AtomicFixnum.new(0)
|
|
76
|
+
@next_retry_at = nil
|
|
77
|
+
log.info "Legion::Cache::Reconnector[#{@tier}] reconnected after #{count} attempts"
|
|
78
|
+
return
|
|
79
|
+
rescue StandardError => e
|
|
80
|
+
@attempts.increment
|
|
81
|
+
handle_exception(e, level: :warn, handled: true,
|
|
82
|
+
operation: :"reconnector_#{@tier}",
|
|
83
|
+
attempt: @attempts.value, next_delay: delay)
|
|
84
|
+
delay = [delay * 2, configured_max_delay].min
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
rescue StandardError => e
|
|
88
|
+
handle_exception(e, level: :error, handled: true, operation: :"reconnector_#{@tier}_loop")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def configured_initial_delay
|
|
92
|
+
return DEFAULT_INITIAL_DELAY unless defined?(Legion::Settings)
|
|
93
|
+
|
|
94
|
+
Legion::Settings.dig(@settings_key, :reconnect, :initial_delay) || DEFAULT_INITIAL_DELAY
|
|
95
|
+
rescue StandardError
|
|
96
|
+
DEFAULT_INITIAL_DELAY
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def configured_max_delay
|
|
100
|
+
return DEFAULT_MAX_DELAY unless defined?(Legion::Settings)
|
|
101
|
+
|
|
102
|
+
Legion::Settings.dig(@settings_key, :reconnect, :max_delay) || DEFAULT_MAX_DELAY
|
|
103
|
+
rescue StandardError
|
|
104
|
+
DEFAULT_MAX_DELAY
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|