activesupport 5.2.7.1 → 6.1.4.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -434
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/array_inquirer.rb +4 -2
  7. data/lib/active_support/backtrace_cleaner.rb +29 -3
  8. data/lib/active_support/benchmarkable.rb +1 -1
  9. data/lib/active_support/cache/file_store.rb +34 -34
  10. data/lib/active_support/cache/mem_cache_store.rb +39 -24
  11. data/lib/active_support/cache/memory_store.rb +59 -33
  12. data/lib/active_support/cache/null_store.rb +8 -3
  13. data/lib/active_support/cache/redis_cache_store.rb +72 -45
  14. data/lib/active_support/cache/strategy/local_cache.rb +41 -26
  15. data/lib/active_support/cache.rb +148 -78
  16. data/lib/active_support/callbacks.rb +81 -64
  17. data/lib/active_support/concern.rb +70 -3
  18. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  19. data/lib/active_support/concurrency/share_lock.rb +0 -1
  20. data/lib/active_support/configurable.rb +10 -14
  21. data/lib/active_support/configuration_file.rb +51 -0
  22. data/lib/active_support/core_ext/array/access.rb +18 -6
  23. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  24. data/lib/active_support/core_ext/array/extract.rb +21 -0
  25. data/lib/active_support/core_ext/array.rb +1 -1
  26. data/lib/active_support/core_ext/benchmark.rb +2 -2
  27. data/lib/active_support/core_ext/class/attribute.rb +32 -47
  28. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  29. data/lib/active_support/core_ext/date/calculations.rb +6 -5
  30. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  31. data/lib/active_support/core_ext/date_and_time/calculations.rb +37 -47
  32. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  33. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  34. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  35. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  36. data/lib/active_support/core_ext/enumerable.rb +171 -75
  37. data/lib/active_support/core_ext/hash/conversions.rb +3 -3
  38. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  39. data/lib/active_support/core_ext/hash/except.rb +2 -2
  40. data/lib/active_support/core_ext/hash/keys.rb +1 -30
  41. data/lib/active_support/core_ext/hash/slice.rb +6 -27
  42. data/lib/active_support/core_ext/hash.rb +1 -2
  43. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  44. data/lib/active_support/core_ext/kernel.rb +0 -1
  45. data/lib/active_support/core_ext/load_error.rb +1 -1
  46. data/lib/active_support/core_ext/marshal.rb +2 -0
  47. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  48. data/lib/active_support/core_ext/module/attribute_accessors.rb +30 -39
  49. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +17 -19
  50. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  51. data/lib/active_support/core_ext/module/delegation.rb +76 -33
  52. data/lib/active_support/core_ext/module/introspection.rb +16 -15
  53. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  54. data/lib/active_support/core_ext/module.rb +0 -1
  55. data/lib/active_support/core_ext/name_error.rb +29 -2
  56. data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
  57. data/lib/active_support/core_ext/numeric.rb +0 -1
  58. data/lib/active_support/core_ext/object/blank.rb +1 -2
  59. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  60. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  61. data/lib/active_support/core_ext/object/json.rb +14 -2
  62. data/lib/active_support/core_ext/object/try.rb +17 -7
  63. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  64. data/lib/active_support/core_ext/range/compare_range.rb +34 -13
  65. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  66. data/lib/active_support/core_ext/range/each.rb +0 -1
  67. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  68. data/lib/active_support/core_ext/regexp.rb +8 -5
  69. data/lib/active_support/core_ext/securerandom.rb +23 -3
  70. data/lib/active_support/core_ext/string/access.rb +5 -16
  71. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  72. data/lib/active_support/core_ext/string/filters.rb +42 -1
  73. data/lib/active_support/core_ext/string/inflections.rb +45 -6
  74. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  75. data/lib/active_support/core_ext/string/multibyte.rb +6 -5
  76. data/lib/active_support/core_ext/string/output_safety.rb +70 -41
  77. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  78. data/lib/active_support/core_ext/string/strip.rb +3 -1
  79. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  80. data/lib/active_support/core_ext/symbol.rb +3 -0
  81. data/lib/active_support/core_ext/time/calculations.rb +51 -3
  82. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  83. data/lib/active_support/core_ext/uri.rb +6 -1
  84. data/lib/active_support/core_ext.rb +1 -1
  85. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  86. data/lib/active_support/current_attributes.rb +16 -2
  87. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  88. data/lib/active_support/dependencies.rb +109 -34
  89. data/lib/active_support/deprecation/behaviors.rb +16 -3
  90. data/lib/active_support/deprecation/disallowed.rb +56 -0
  91. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  92. data/lib/active_support/deprecation/method_wrappers.rb +18 -23
  93. data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
  94. data/lib/active_support/deprecation/reporting.rb +50 -7
  95. data/lib/active_support/deprecation.rb +6 -1
  96. data/lib/active_support/descendants_tracker.rb +59 -9
  97. data/lib/active_support/duration/iso8601_parser.rb +2 -4
  98. data/lib/active_support/duration/iso8601_serializer.rb +18 -14
  99. data/lib/active_support/duration.rb +78 -30
  100. data/lib/active_support/encrypted_configuration.rb +0 -4
  101. data/lib/active_support/encrypted_file.rb +22 -4
  102. data/lib/active_support/environment_inquirer.rb +20 -0
  103. data/lib/active_support/evented_file_update_checker.rb +82 -117
  104. data/lib/active_support/execution_wrapper.rb +2 -1
  105. data/lib/active_support/file_update_checker.rb +0 -1
  106. data/lib/active_support/fork_tracker.rb +64 -0
  107. data/lib/active_support/gem_version.rb +4 -4
  108. data/lib/active_support/hash_with_indifferent_access.rb +70 -42
  109. data/lib/active_support/i18n.rb +1 -0
  110. data/lib/active_support/i18n_railtie.rb +15 -8
  111. data/lib/active_support/inflector/inflections.rb +2 -7
  112. data/lib/active_support/inflector/methods.rb +49 -58
  113. data/lib/active_support/inflector/transliterate.rb +47 -18
  114. data/lib/active_support/json/decoding.rb +25 -26
  115. data/lib/active_support/json/encoding.rb +11 -3
  116. data/lib/active_support/key_generator.rb +1 -33
  117. data/lib/active_support/lazy_load_hooks.rb +5 -2
  118. data/lib/active_support/locale/en.rb +33 -0
  119. data/lib/active_support/locale/en.yml +7 -3
  120. data/lib/active_support/log_subscriber.rb +39 -9
  121. data/lib/active_support/logger.rb +2 -17
  122. data/lib/active_support/logger_silence.rb +11 -19
  123. data/lib/active_support/logger_thread_safe_level.rb +50 -6
  124. data/lib/active_support/message_encryptor.rb +8 -13
  125. data/lib/active_support/message_verifier.rb +10 -10
  126. data/lib/active_support/messages/metadata.rb +11 -2
  127. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  128. data/lib/active_support/messages/rotator.rb +10 -9
  129. data/lib/active_support/multibyte/chars.rb +10 -68
  130. data/lib/active_support/multibyte/unicode.rb +15 -327
  131. data/lib/active_support/notifications/fanout.rb +116 -16
  132. data/lib/active_support/notifications/instrumenter.rb +71 -9
  133. data/lib/active_support/notifications.rb +72 -8
  134. data/lib/active_support/number_helper/number_converter.rb +5 -6
  135. data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
  136. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
  137. data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
  138. data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -3
  139. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  140. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  141. data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -7
  142. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  143. data/lib/active_support/number_helper.rb +38 -12
  144. data/lib/active_support/option_merger.rb +22 -3
  145. data/lib/active_support/ordered_hash.rb +1 -1
  146. data/lib/active_support/ordered_options.rb +13 -3
  147. data/lib/active_support/parameter_filter.rb +133 -0
  148. data/lib/active_support/per_thread_registry.rb +1 -1
  149. data/lib/active_support/rails.rb +1 -10
  150. data/lib/active_support/railtie.rb +23 -1
  151. data/lib/active_support/reloader.rb +4 -5
  152. data/lib/active_support/rescuable.rb +4 -4
  153. data/lib/active_support/secure_compare_rotator.rb +51 -0
  154. data/lib/active_support/security_utils.rb +19 -12
  155. data/lib/active_support/string_inquirer.rb +4 -3
  156. data/lib/active_support/subscriber.rb +72 -28
  157. data/lib/active_support/tagged_logging.rb +42 -8
  158. data/lib/active_support/test_case.rb +91 -0
  159. data/lib/active_support/testing/assertions.rb +30 -9
  160. data/lib/active_support/testing/deprecation.rb +0 -1
  161. data/lib/active_support/testing/file_fixtures.rb +2 -0
  162. data/lib/active_support/testing/isolation.rb +2 -2
  163. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  164. data/lib/active_support/testing/parallelization/server.rb +78 -0
  165. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  166. data/lib/active_support/testing/parallelization.rb +51 -0
  167. data/lib/active_support/testing/stream.rb +1 -2
  168. data/lib/active_support/testing/time_helpers.rb +47 -12
  169. data/lib/active_support/time_with_zone.rb +81 -47
  170. data/lib/active_support/values/time_zone.rb +32 -17
  171. data/lib/active_support/xml_mini/jdom.rb +2 -3
  172. data/lib/active_support/xml_mini/libxml.rb +2 -2
  173. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  174. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  175. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  176. data/lib/active_support/xml_mini/rexml.rb +10 -3
  177. data/lib/active_support/xml_mini.rb +2 -10
  178. data/lib/active_support.rb +14 -1
  179. metadata +55 -29
  180. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
  181. data/lib/active_support/core_ext/hash/compact.rb +0 -29
  182. data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
  183. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  184. data/lib/active_support/core_ext/module/reachable.rb +0 -11
  185. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
  186. data/lib/active_support/core_ext/range/include_range.rb +0 -3
  187. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -12,6 +12,11 @@ module ActiveSupport
12
12
  class NullStore < Store
13
13
  prepend Strategy::LocalCache
14
14
 
15
+ # Advertise cache versioning support.
16
+ def self.supports_cache_versioning?
17
+ true
18
+ end
19
+
15
20
  def clear(options = nil)
16
21
  end
17
22
 
@@ -28,14 +33,14 @@ module ActiveSupport
28
33
  end
29
34
 
30
35
  private
31
- def read_entry(key, options)
36
+ def read_entry(key, **options)
32
37
  end
33
38
 
34
- def write_entry(key, entry, options)
39
+ def write_entry(key, entry, **options)
35
40
  true
36
41
  end
37
42
 
38
- def delete_entry(key, options)
43
+ def delete_entry(key, **options)
39
44
  false
40
45
  end
41
46
  end
@@ -17,7 +17,6 @@ end
17
17
 
18
18
  require "digest/sha2"
19
19
  require "active_support/core_ext/marshal"
20
- require "active_support/core_ext/hash/transform_values"
21
20
 
22
21
  module ActiveSupport
23
22
  module Cache
@@ -67,27 +66,32 @@ module ActiveSupport
67
66
  SCAN_BATCH_SIZE = 1000
68
67
  private_constant :SCAN_BATCH_SIZE
69
68
 
69
+ # Advertise cache versioning support.
70
+ def self.supports_cache_versioning?
71
+ true
72
+ end
73
+
70
74
  # Support raw values in the local cache strategy.
71
75
  module LocalCacheWithRaw # :nodoc:
72
76
  private
73
- def write_entry(key, entry, options)
77
+ def write_entry(key, entry, **options)
74
78
  if options[:raw] && local_cache
75
79
  raw_entry = Entry.new(serialize_entry(entry, raw: true))
76
80
  raw_entry.expires_at = entry.expires_at
77
- super(key, raw_entry, options)
81
+ super(key, raw_entry, **options)
78
82
  else
79
83
  super
80
84
  end
81
85
  end
82
86
 
83
- def write_multi_entries(entries, options)
87
+ def write_multi_entries(entries, **options)
84
88
  if options[:raw] && local_cache
85
89
  raw_entries = entries.map do |key, entry|
86
90
  raw_entry = Entry.new(serialize_entry(entry, raw: true))
87
91
  raw_entry.expires_at = entry.expires_at
88
92
  end.to_h
89
93
 
90
- super(raw_entries, options)
94
+ super(raw_entries, **options)
91
95
  else
92
96
  super
93
97
  end
@@ -140,15 +144,17 @@ module ActiveSupport
140
144
 
141
145
  # Creates a new Redis cache store.
142
146
  #
143
- # Handles three options: block provided to instantiate, single URL
144
- # provided, and multiple URLs provided.
147
+ # Handles four options: :redis block, :redis instance, single :url
148
+ # string, and multiple :url strings.
145
149
  #
146
- # :redis Proc -> options[:redis].call
147
- # :url String -> Redis.new(url: …)
148
- # :url Array -> Redis::Distributed.new([{ url: … }, { url: … }, …])
150
+ # Option Class Result
151
+ # :redis Proc -> options[:redis].call
152
+ # :redis Object -> options[:redis]
153
+ # :url String -> Redis.new(url: …)
154
+ # :url Array -> Redis::Distributed.new([{ url: … }, { url: … }, …])
149
155
  #
150
156
  # No namespace is set by default. Provide one if the Redis cache
151
- # server is shared with other apps: <tt>namespace: 'myapp-cache'<tt>.
157
+ # server is shared with other apps: <tt>namespace: 'myapp-cache'</tt>.
152
158
  #
153
159
  # Compression is enabled by default with a 1kB threshold, so cached
154
160
  # values larger than 1kB are automatically compressed. Disable by
@@ -163,7 +169,7 @@ module ActiveSupport
163
169
  # Race condition TTL is not set by default. This can be used to avoid
164
170
  # "thundering herd" cache writes when hot cache entries are expired.
165
171
  # See <tt>ActiveSupport::Cache::Store#fetch</tt> for more.
166
- def initialize(namespace: nil, compress: true, compress_threshold: 1.kilobyte, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
172
+ def initialize(namespace: nil, compress: true, compress_threshold: 1.kilobyte, coder: DEFAULT_CODER, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
167
173
  @redis_options = redis_options
168
174
 
169
175
  @max_key_bytesize = MAX_KEY_BYTESIZE
@@ -171,7 +177,8 @@ module ActiveSupport
171
177
 
172
178
  super namespace: namespace,
173
179
  compress: compress, compress_threshold: compress_threshold,
174
- expires_in: expires_in, race_condition_ttl: race_condition_ttl
180
+ expires_in: expires_in, race_condition_ttl: race_condition_ttl,
181
+ coder: coder
175
182
  end
176
183
 
177
184
  def redis
@@ -189,7 +196,7 @@ module ActiveSupport
189
196
 
190
197
  def inspect
191
198
  instance = @redis || @redis_options
192
- "<##{self.class} options=#{options.inspect} redis=#{instance.inspect}>"
199
+ "#<#{self.class} options=#{options.inspect} redis=#{instance.inspect}>"
193
200
  end
194
201
 
195
202
  # Cache Store API implementation.
@@ -232,10 +239,14 @@ module ActiveSupport
232
239
  pattern = namespace_key(matcher, options)
233
240
  cursor = "0"
234
241
  # Fetch keys in batches using SCAN to avoid blocking the Redis server.
235
- begin
236
- cursor, keys = c.scan(cursor, match: pattern, count: SCAN_BATCH_SIZE)
237
- c.del(*keys) unless keys.empty?
238
- end until cursor == "0"
242
+ nodes = c.respond_to?(:nodes) ? c.nodes : [c]
243
+
244
+ nodes.each do |node|
245
+ begin
246
+ cursor, keys = node.scan(cursor, match: pattern, count: SCAN_BATCH_SIZE)
247
+ node.del(*keys) unless keys.empty?
248
+ end until cursor == "0"
249
+ end
239
250
  end
240
251
  end
241
252
  end
@@ -251,7 +262,14 @@ module ActiveSupport
251
262
  def increment(name, amount = 1, options = nil)
252
263
  instrument :increment, name, amount: amount do
253
264
  failsafe :increment do
254
- redis.with { |c| c.incrby normalize_key(name, options), amount }
265
+ options = merged_options(options)
266
+ key = normalize_key(name, options)
267
+
268
+ redis.with do |c|
269
+ c.incrby(key, amount).tap do
270
+ write_key_expiry(c, key, options)
271
+ end
272
+ end
255
273
  end
256
274
  end
257
275
  end
@@ -267,7 +285,14 @@ module ActiveSupport
267
285
  def decrement(name, amount = 1, options = nil)
268
286
  instrument :decrement, name, amount: amount do
269
287
  failsafe :decrement do
270
- redis.with { |c| c.decrby normalize_key(name, options), amount }
288
+ options = merged_options(options)
289
+ key = normalize_key(name, options)
290
+
291
+ redis.with do |c|
292
+ c.decrby(key, amount).tap do
293
+ write_key_expiry(c, key, options)
294
+ end
295
+ end
271
296
  end
272
297
  end
273
298
  end
@@ -318,16 +343,16 @@ module ActiveSupport
318
343
 
319
344
  # Store provider interface:
320
345
  # Read an entry from the cache.
321
- def read_entry(key, options = nil)
346
+ def read_entry(key, **options)
322
347
  failsafe :read_entry do
323
- raw = options && options.fetch(:raw, false)
348
+ raw = options&.fetch(:raw, false)
324
349
  deserialize_entry(redis.with { |c| c.get(key) }, raw: raw)
325
350
  end
326
351
  end
327
352
 
328
- def read_multi_entries(names, _options)
353
+ def read_multi_entries(names, **options)
329
354
  if mget_capable?
330
- read_multi_mget(*names)
355
+ read_multi_mget(*names, **options)
331
356
  else
332
357
  super
333
358
  end
@@ -336,7 +361,8 @@ module ActiveSupport
336
361
  def read_multi_mget(*names)
337
362
  options = names.extract_options!
338
363
  options = merged_options(options)
339
- raw = options && options.fetch(:raw, false)
364
+ return {} if names == []
365
+ raw = options&.fetch(:raw, false)
340
366
 
341
367
  keys = names.map { |name| normalize_key(name, options) }
342
368
 
@@ -373,13 +399,19 @@ module ActiveSupport
373
399
  modifiers[:nx] = unless_exist
374
400
  modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in
375
401
 
376
- redis.with { |c| c.set key, serialized_entry, modifiers }
402
+ redis.with { |c| c.set key, serialized_entry, **modifiers }
377
403
  else
378
404
  redis.with { |c| c.set key, serialized_entry }
379
405
  end
380
406
  end
381
407
  end
382
408
 
409
+ def write_key_expiry(client, key, options)
410
+ if options[:expires_in] && client.ttl(key).negative?
411
+ client.expire key, options[:expires_in].to_i
412
+ end
413
+ end
414
+
383
415
  # Delete an entry from the cache.
384
416
  def delete_entry(key, options)
385
417
  failsafe :delete_entry, returning: false do
@@ -387,6 +419,11 @@ module ActiveSupport
387
419
  end
388
420
  end
389
421
 
422
+ # Deletes multiple entries in the cache. Returns the number of entries deleted.
423
+ def delete_multi_entries(entries, **_options)
424
+ redis.with { |c| c.del(entries) }
425
+ end
426
+
390
427
  # Nonstandard store provider API to write multiple values at once.
391
428
  def write_multi_entries(entries, expires_in: nil, **options)
392
429
  if entries.any?
@@ -402,11 +439,11 @@ module ActiveSupport
402
439
 
403
440
  # Truncate keys that exceed 1kB.
404
441
  def normalize_key(key, options)
405
- truncate_key super.b
442
+ truncate_key super&.b
406
443
  end
407
444
 
408
445
  def truncate_key(key)
409
- if key.bytesize > max_key_bytesize
446
+ if key && key.bytesize > max_key_bytesize
410
447
  suffix = ":sha2:#{::Digest::SHA2.hexdigest(key)}"
411
448
  truncate_at = max_key_bytesize - suffix.bytesize
412
449
  "#{key.byteslice(0, truncate_at)}#{suffix}"
@@ -415,21 +452,11 @@ module ActiveSupport
415
452
  end
416
453
  end
417
454
 
418
- def deserialize_entry(serialized_entry, raw:)
419
- if serialized_entry
420
- entry = Marshal.load(serialized_entry) rescue serialized_entry
421
-
422
- written_raw = serialized_entry.equal?(entry)
423
- if raw != written_raw
424
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
425
- Using a different value for the raw option when reading and writing
426
- to a cache key is deprecated for :redis_cache_store and Rails 6.0
427
- will stop automatically detecting the format when reading to avoid
428
- marshal loading untrusted raw strings.
429
- MSG
430
- end
431
-
432
- entry.is_a?(Entry) ? entry : Entry.new(entry)
455
+ def deserialize_entry(payload, raw:)
456
+ if payload && raw
457
+ Entry.new(payload, compress: false)
458
+ else
459
+ super(payload)
433
460
  end
434
461
  end
435
462
 
@@ -437,7 +464,7 @@ module ActiveSupport
437
464
  if raw
438
465
  entry.value.to_s
439
466
  else
440
- Marshal.dump(entry)
467
+ super(entry)
441
468
  end
442
469
  end
443
470
 
@@ -449,7 +476,7 @@ module ActiveSupport
449
476
 
450
477
  def failsafe(method, returning: nil)
451
478
  yield
452
- rescue ::Redis::BaseConnectionError => e
479
+ rescue ::Redis::BaseError => e
453
480
  handle_exception exception: e, method: method, returning: returning
454
481
  returning
455
482
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/object/duplicable"
4
3
  require "active_support/core_ext/string/inflections"
5
4
  require "active_support/per_thread_registry"
6
5
 
@@ -50,32 +49,36 @@ module ActiveSupport
50
49
  @data.clear
51
50
  end
52
51
 
53
- def read_entry(key, options)
52
+ def read_entry(key, **options)
54
53
  @data[key]
55
54
  end
56
55
 
57
- def read_multi_entries(keys, options)
56
+ def read_multi_entries(keys, **options)
58
57
  values = {}
59
58
 
60
59
  keys.each do |name|
61
- entry = read_entry(name, options)
60
+ entry = read_entry(name, **options)
62
61
  values[name] = entry.value if entry
63
62
  end
64
63
 
65
64
  values
66
65
  end
67
66
 
68
- def write_entry(key, value, options)
69
- @data[key] = value
67
+ def write_entry(key, entry, **options)
68
+ entry.dup_value!
69
+ @data[key] = entry
70
70
  true
71
71
  end
72
72
 
73
- def delete_entry(key, options)
73
+ def delete_entry(key, **options)
74
74
  !!@data.delete(key)
75
75
  end
76
76
 
77
77
  def fetch_entry(key, options = nil) # :nodoc:
78
- @data.fetch(key) { @data[key] = yield }
78
+ entry = @data.fetch(key) { @data[key] = yield }
79
+ dup_entry = entry.dup
80
+ dup_entry&.dup_value!
81
+ dup_entry
79
82
  end
80
83
  end
81
84
 
@@ -92,77 +95,89 @@ module ActiveSupport
92
95
  local_cache_key)
93
96
  end
94
97
 
95
- def clear(options = nil) # :nodoc:
98
+ def clear(**options) # :nodoc:
96
99
  return super unless cache = local_cache
97
100
  cache.clear(options)
98
101
  super
99
102
  end
100
103
 
101
- def cleanup(options = nil) # :nodoc:
104
+ def cleanup(**options) # :nodoc:
102
105
  return super unless cache = local_cache
103
106
  cache.clear
104
107
  super
105
108
  end
106
109
 
107
- def increment(name, amount = 1, options = nil) # :nodoc:
110
+ def delete_matched(matcher, options = nil) # :nodoc:
111
+ return super unless cache = local_cache
112
+ cache.clear
113
+ super
114
+ end
115
+
116
+ def increment(name, amount = 1, **options) # :nodoc:
108
117
  return super unless local_cache
109
118
  value = bypass_local_cache { super }
110
- write_cache_value(name, value, options)
119
+ write_cache_value(name, value, **options)
111
120
  value
112
121
  end
113
122
 
114
- def decrement(name, amount = 1, options = nil) # :nodoc:
123
+ def decrement(name, amount = 1, **options) # :nodoc:
115
124
  return super unless local_cache
116
125
  value = bypass_local_cache { super }
117
- write_cache_value(name, value, options)
126
+ write_cache_value(name, value, **options)
118
127
  value
119
128
  end
120
129
 
121
130
  private
122
- def read_entry(key, options)
131
+ def read_entry(key, **options)
123
132
  if cache = local_cache
124
- cache.fetch_entry(key) { super }
133
+ hit = true
134
+ value = cache.fetch_entry(key) do
135
+ hit = false
136
+ super
137
+ end
138
+ options[:event][:store] = cache.class.name if hit && options[:event]
139
+ value
125
140
  else
126
141
  super
127
142
  end
128
143
  end
129
144
 
130
- def read_multi_entries(keys, options)
145
+ def read_multi_entries(keys, **options)
131
146
  return super unless local_cache
132
147
 
133
- local_entries = local_cache.read_multi_entries(keys, options)
148
+ local_entries = local_cache.read_multi_entries(keys, **options)
134
149
  missed_keys = keys - local_entries.keys
135
150
 
136
151
  if missed_keys.any?
137
- local_entries.merge!(super(missed_keys, options))
152
+ local_entries.merge!(super(missed_keys, **options))
138
153
  else
139
154
  local_entries
140
155
  end
141
156
  end
142
157
 
143
- def write_entry(key, entry, options)
158
+ def write_entry(key, entry, **options)
144
159
  if options[:unless_exist]
145
- local_cache.delete_entry(key, options) if local_cache
160
+ local_cache.delete_entry(key, **options) if local_cache
146
161
  else
147
- local_cache.write_entry(key, entry, options) if local_cache
162
+ local_cache.write_entry(key, entry, **options) if local_cache
148
163
  end
149
164
 
150
165
  super
151
166
  end
152
167
 
153
- def delete_entry(key, options)
154
- local_cache.delete_entry(key, options) if local_cache
168
+ def delete_entry(key, **options)
169
+ local_cache.delete_entry(key, **options) if local_cache
155
170
  super
156
171
  end
157
172
 
158
- def write_cache_value(name, value, options)
173
+ def write_cache_value(name, value, **options)
159
174
  name = normalize_key(name, options)
160
175
  cache = local_cache
161
176
  cache.mute do
162
177
  if value
163
178
  cache.write(name, value, options)
164
179
  else
165
- cache.delete(name, options)
180
+ cache.delete(name, **options)
166
181
  end
167
182
  end
168
183
  end