legion-cache 1.3.20 → 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.
data/lib/legion/cache.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'legion/logging/helper'
3
4
  require 'legion/cache/version'
4
5
  require 'legion/cache/settings'
5
6
  require 'legion/cache/cacheable'
@@ -13,13 +14,22 @@ require 'legion/cache/helper'
13
14
 
14
15
  module Legion
15
16
  module Cache
16
- if Legion::Cache::Settings.normalize_driver(Legion::Settings[:cache][:driver]) == 'redis'
17
- extend Legion::Cache::Redis
18
- else
19
- extend Legion::Cache::Memcached
20
- end
17
+ extend Legion::Logging::Helper
21
18
 
22
19
  class << self
20
+ include Legion::Logging::Helper
21
+
22
+ def connected?
23
+ @connected == true
24
+ end
25
+
26
+ def driver_name
27
+ return 'memory' if @using_memory
28
+ return 'local' if @using_local
29
+
30
+ @active_shared_driver || configured_shared_driver
31
+ end
32
+
23
33
  def setup(**)
24
34
  return Legion::Settings[:cache][:connected] = true if connected?
25
35
 
@@ -28,16 +38,17 @@ module Legion
28
38
  @using_memory = true
29
39
  @connected = true
30
40
  Legion::Settings[:cache][:connected] = true
31
- Legion::Logging.info 'Legion::Cache using in-memory adapter (lite mode)' if defined?(Legion::Logging)
41
+ log.info 'Legion::Cache using in-memory adapter (lite mode)'
32
42
  return
33
43
  end
34
44
 
45
+ log.debug { "Legion::Cache setup driver=#{Legion::Settings[:cache][:driver]} servers=#{Array(Legion::Settings[:cache][:servers]).size}" }
35
46
  setup_local
36
47
  setup_shared(**)
37
48
  end
38
49
 
39
50
  def shutdown
40
- Legion::Logging.info 'Shutting down Legion::Cache'
51
+ log.info 'Shutting down Legion::Cache'
41
52
  if @using_memory
42
53
  Legion::Cache::Memory.shutdown
43
54
  else
@@ -58,10 +69,39 @@ module Legion
58
69
  @using_local == true
59
70
  end
60
71
 
72
+ def using_memory?
73
+ @using_memory == true
74
+ end
75
+
76
+ def client(**opts)
77
+ if ENV['LEGION_MODE'] == 'lite'
78
+ Legion::Cache::Memory.setup unless Legion::Cache::Memory.connected?
79
+ @using_memory = true
80
+ @using_local = false
81
+ @connected = true
82
+ @active_shared_driver = nil
83
+ Legion::Settings[:cache][:connected] = true if defined?(Legion::Settings)
84
+ return Legion::Cache::Memory.client
85
+ end
86
+
87
+ configure_shared_adapter!(opts[:driver])
88
+ @using_memory = false
89
+ @using_local = false
90
+ result = super
91
+ @connected = true
92
+ Legion::Settings[:cache][:connected] = true if defined?(Legion::Settings)
93
+ result
94
+ rescue StandardError
95
+ @connected = false
96
+ Legion::Settings[:cache][:connected] = false if defined?(Legion::Settings)
97
+ raise
98
+ end
99
+
61
100
  def get(key)
62
101
  return Legion::Cache::Memory.get(key) if @using_memory
63
102
  return Legion::Cache::Local.get(key) if @using_local
64
103
 
104
+ configure_shared_adapter!
65
105
  super
66
106
  end
67
107
 
@@ -69,7 +109,8 @@ module Legion
69
109
  return 3600 unless defined?(Legion::Settings)
70
110
 
71
111
  Legion::Settings.dig(:cache, :compliance, :phi_max_ttl) || 3600
72
- rescue StandardError
112
+ rescue StandardError => e
113
+ handle_exception(e, level: :warn, handled: true, operation: :cache_phi_max_ttl)
73
114
  3600
74
115
  end
75
116
 
@@ -86,13 +127,15 @@ module Legion
86
127
  return Legion::Cache::Memory.set(key, value, effective_ttl) if @using_memory
87
128
  return Legion::Cache::Local.set(key, value, effective_ttl) if @using_local
88
129
 
130
+ configure_shared_adapter!
89
131
  super(key, value, effective_ttl)
90
132
  end
91
133
 
92
- def fetch(key, ttl = nil)
93
- return Legion::Cache::Memory.fetch(key, ttl) if @using_memory
94
- return Legion::Cache::Local.fetch(key, ttl) if @using_local
134
+ def fetch(key, ttl = nil, &)
135
+ return Legion::Cache::Memory.fetch(key, ttl, &) if @using_memory
136
+ return Legion::Cache::Local.fetch(key, ttl, &) if @using_local
95
137
 
138
+ configure_shared_adapter!
96
139
  super
97
140
  end
98
141
 
@@ -100,6 +143,7 @@ module Legion
100
143
  return Legion::Cache::Memory.delete(key) if @using_memory
101
144
  return Legion::Cache::Local.delete(key) if @using_local
102
145
 
146
+ configure_shared_adapter!
103
147
  super
104
148
  end
105
149
 
@@ -107,6 +151,94 @@ module Legion
107
151
  return Legion::Cache::Memory.flush(delay) if @using_memory
108
152
  return Legion::Cache::Local.flush(delay) if @using_local
109
153
 
154
+ configure_shared_adapter!
155
+ super
156
+ end
157
+
158
+ def mget(*keys)
159
+ keys = keys.flatten
160
+ return {} if keys.empty?
161
+ return keys.to_h { |key| [key, Legion::Cache::Memory.get(key)] } if @using_memory
162
+ return local_mget(*keys) if @using_local
163
+
164
+ configure_shared_adapter!
165
+ super
166
+ end
167
+
168
+ def mset(hash)
169
+ return true if hash.empty?
170
+ return hash.each { |key, value| Legion::Cache::Memory.set(key, value) } && true if @using_memory
171
+ return local_mset(hash) if @using_local
172
+
173
+ configure_shared_adapter!
174
+ super
175
+ end
176
+
177
+ def close
178
+ if @using_memory
179
+ Legion::Cache::Memory.shutdown
180
+ @using_memory = false
181
+ @connected = false
182
+ Legion::Settings[:cache][:connected] = false if defined?(Legion::Settings)
183
+ return false
184
+ end
185
+
186
+ if @using_local
187
+ Legion::Cache::Local.close
188
+ @using_local = false
189
+ @connected = false
190
+ Legion::Settings[:cache][:connected] = false if defined?(Legion::Settings)
191
+ return false
192
+ end
193
+
194
+ return false unless instance_variable_defined?(:@client) && @client
195
+
196
+ configure_shared_adapter!
197
+ result = super
198
+ @connected = false
199
+ Legion::Settings[:cache][:connected] = false if defined?(Legion::Settings)
200
+ result
201
+ end
202
+
203
+ def restart(**opts)
204
+ configure_shared_adapter!(opts[:driver])
205
+ @using_memory = false
206
+ @using_local = false
207
+ result = super
208
+ @connected = true
209
+ Legion::Settings[:cache][:connected] = true if defined?(Legion::Settings)
210
+ result
211
+ end
212
+
213
+ def size
214
+ return Legion::Cache::Memory.size if @using_memory
215
+ return Legion::Cache::Local.size if @using_local
216
+
217
+ configure_shared_adapter!
218
+ super
219
+ end
220
+
221
+ def available
222
+ return Legion::Cache::Memory.available if @using_memory
223
+ return Legion::Cache::Local.available if @using_local
224
+
225
+ configure_shared_adapter!
226
+ super
227
+ end
228
+
229
+ def pool_size
230
+ return Legion::Cache::Memory.size if @using_memory
231
+ return Legion::Cache::Local.pool_size if @using_local
232
+
233
+ configure_shared_adapter!
234
+ super
235
+ end
236
+
237
+ def timeout
238
+ return 0 if @using_memory
239
+ return Legion::Cache::Local.timeout if @using_local
240
+
241
+ configure_shared_adapter!
110
242
  super
111
243
  end
112
244
 
@@ -117,30 +249,85 @@ module Legion
117
249
 
118
250
  Legion::Cache::Local.setup
119
251
  rescue StandardError => e
120
- Legion::Logging.warn "Local cache setup failed: #{e.message}" if defined?(Legion::Logging)
252
+ report_exception(e, level: :warn, handled: true, operation: :setup_local)
121
253
  end
122
254
 
123
255
  def setup_shared(**)
124
- client(**Legion::Settings[:cache], **)
256
+ client(**Legion::Settings[:cache], logger: log, **)
125
257
  @connected = true
126
258
  @using_local = false
127
259
  Legion::Settings[:cache][:connected] = true
128
- if defined?(Legion::Logging)
129
- driver = Legion::Settings[:cache][:driver] || 'dalli'
130
- servers = Array(Legion::Settings[:cache][:servers]).join(', ')
131
- Legion::Logging.info "Legion::Cache connected (driver=#{driver}) to #{servers}"
132
- end
260
+ driver = Legion::Settings[:cache][:driver] || 'dalli'
261
+ servers = Array(Legion::Settings[:cache][:servers]).join(', ')
262
+ log.info "Legion::Cache connected (driver=#{driver}) to #{servers}"
133
263
  rescue StandardError => e
134
- Legion::Logging.warn "Shared cache unavailable (#{e.message}), falling back to Local" if defined?(Legion::Logging)
264
+ report_exception(e, level: :warn, handled: true, operation: :setup_shared, fallback: :local)
135
265
  if Legion::Cache::Local.connected?
136
266
  @using_local = true
137
267
  @connected = true
138
268
  Legion::Settings[:cache][:connected] = true
269
+ log.info 'Legion::Cache fell back to Local cache'
139
270
  else
140
271
  @connected = false
141
272
  Legion::Settings[:cache][:connected] = false
273
+ log.error 'Legion::Cache shared and local adapters are unavailable'
274
+ end
275
+ end
276
+
277
+ def report_exception(exception, level:, handled:, **)
278
+ handle_exception(exception, level: level, handled: handled, **)
279
+ end
280
+
281
+ def configure_shared_adapter!(requested_driver = nil)
282
+ driver = Legion::Cache::Settings.normalize_driver(requested_driver || configured_shared_driver)
283
+ return if @active_shared_driver == driver
284
+
285
+ close_existing_shared_client
286
+ extend build_shared_adapter(driver)
287
+
288
+ @active_shared_driver = driver
289
+ log.info "Legion::Cache selected shared adapter=#{driver}"
290
+ end
291
+
292
+ def configured_shared_driver
293
+ if defined?(Legion::Settings)
294
+ Legion::Cache::Settings.normalize_driver(Legion::Settings.dig(:cache, :driver) || Legion::Cache::Settings.driver)
295
+ else
296
+ Legion::Cache::Settings.driver
297
+ end
298
+ rescue StandardError => e
299
+ handle_exception(e, level: :warn, handled: true, operation: :cache_configured_shared_driver)
300
+ 'dalli'
301
+ end
302
+
303
+ def build_shared_adapter(driver)
304
+ case Legion::Cache::Settings.normalize_driver(driver)
305
+ when 'redis'
306
+ Legion::Cache::Redis.dup
307
+ else
308
+ Legion::Cache::Memcached.dup
142
309
  end
143
310
  end
311
+
312
+ def close_existing_shared_client
313
+ return unless instance_variable_defined?(:@client) && @client
314
+
315
+ @client.shutdown(&:close)
316
+ rescue StandardError => e
317
+ handle_exception(e, level: :warn, handled: true, operation: :cache_close_existing_shared_client)
318
+ ensure
319
+ @client = nil
320
+ @connected = false
321
+ end
322
+
323
+ def local_mget(*keys)
324
+ keys.to_h { |key| [key, Legion::Cache::Local.get(key)] }
325
+ end
326
+
327
+ def local_mset(hash)
328
+ hash.each { |key, value| Legion::Cache::Local.set(key, value) }
329
+ true
330
+ end
144
331
  end
145
332
  end
146
333
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.20
4
+ version: 1.3.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -43,14 +43,14 @@ dependencies:
43
43
  requirements:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 1.2.8
46
+ version: 1.5.0
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 1.2.8
53
+ version: 1.5.0
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: legion-settings
56
56
  requirement: !ruby/object:Gem::Requirement