activesupport 5.2.0 → 6.1.0

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 (190) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +362 -333
  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 +33 -33
  10. data/lib/active_support/cache/mem_cache_store.rb +31 -29
  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 +84 -45
  14. data/lib/active_support/cache/strategy/local_cache.rb +41 -26
  15. data/lib/active_support/cache.rb +174 -113
  16. data/lib/active_support/callbacks.rb +81 -64
  17. data/lib/active_support/concern.rb +76 -5
  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 +46 -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/digest.rb +3 -0
  37. data/lib/active_support/core_ext/enumerable.rb +171 -70
  38. data/lib/active_support/core_ext/file/atomic.rb +1 -1
  39. data/lib/active_support/core_ext/hash/conversions.rb +3 -3
  40. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  41. data/lib/active_support/core_ext/hash/except.rb +2 -2
  42. data/lib/active_support/core_ext/hash/keys.rb +1 -30
  43. data/lib/active_support/core_ext/hash/slice.rb +6 -27
  44. data/lib/active_support/core_ext/hash.rb +1 -2
  45. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  46. data/lib/active_support/core_ext/kernel.rb +0 -1
  47. data/lib/active_support/core_ext/load_error.rb +1 -1
  48. data/lib/active_support/core_ext/marshal.rb +2 -0
  49. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  50. data/lib/active_support/core_ext/module/attribute_accessors.rb +30 -39
  51. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +17 -19
  52. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  53. data/lib/active_support/core_ext/module/delegation.rb +76 -33
  54. data/lib/active_support/core_ext/module/introspection.rb +16 -15
  55. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  56. data/lib/active_support/core_ext/module.rb +0 -1
  57. data/lib/active_support/core_ext/name_error.rb +29 -2
  58. data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
  59. data/lib/active_support/core_ext/numeric.rb +0 -1
  60. data/lib/active_support/core_ext/object/blank.rb +1 -2
  61. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  62. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  63. data/lib/active_support/core_ext/object/json.rb +7 -2
  64. data/lib/active_support/core_ext/object/to_query.rb +5 -2
  65. data/lib/active_support/core_ext/object/try.rb +17 -7
  66. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  67. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  68. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  69. data/lib/active_support/core_ext/range/each.rb +0 -1
  70. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  71. data/lib/active_support/core_ext/range.rb +1 -1
  72. data/lib/active_support/core_ext/regexp.rb +8 -5
  73. data/lib/active_support/core_ext/securerandom.rb +23 -3
  74. data/lib/active_support/core_ext/string/access.rb +5 -16
  75. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  76. data/lib/active_support/core_ext/string/filters.rb +42 -1
  77. data/lib/active_support/core_ext/string/inflections.rb +45 -6
  78. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  79. data/lib/active_support/core_ext/string/multibyte.rb +6 -5
  80. data/lib/active_support/core_ext/string/output_safety.rb +69 -12
  81. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  82. data/lib/active_support/core_ext/string/strip.rb +3 -1
  83. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  84. data/lib/active_support/core_ext/symbol.rb +3 -0
  85. data/lib/active_support/core_ext/time/calculations.rb +50 -3
  86. data/lib/active_support/core_ext/time/conversions.rb +1 -0
  87. data/lib/active_support/core_ext/uri.rb +7 -5
  88. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  89. data/lib/active_support/current_attributes.rb +15 -2
  90. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  91. data/lib/active_support/dependencies.rb +118 -35
  92. data/lib/active_support/deprecation/behaviors.rb +20 -3
  93. data/lib/active_support/deprecation/disallowed.rb +56 -0
  94. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  95. data/lib/active_support/deprecation/method_wrappers.rb +21 -13
  96. data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
  97. data/lib/active_support/deprecation/reporting.rb +51 -8
  98. data/lib/active_support/deprecation.rb +6 -1
  99. data/lib/active_support/descendants_tracker.rb +59 -9
  100. data/lib/active_support/duration/iso8601_parser.rb +2 -4
  101. data/lib/active_support/duration/iso8601_serializer.rb +18 -14
  102. data/lib/active_support/duration.rb +90 -38
  103. data/lib/active_support/encrypted_configuration.rb +1 -5
  104. data/lib/active_support/encrypted_file.rb +23 -5
  105. data/lib/active_support/environment_inquirer.rb +20 -0
  106. data/lib/active_support/evented_file_update_checker.rb +82 -117
  107. data/lib/active_support/execution_wrapper.rb +1 -0
  108. data/lib/active_support/file_update_checker.rb +0 -1
  109. data/lib/active_support/fork_tracker.rb +62 -0
  110. data/lib/active_support/gem_version.rb +2 -2
  111. data/lib/active_support/hash_with_indifferent_access.rb +78 -41
  112. data/lib/active_support/i18n.rb +1 -0
  113. data/lib/active_support/i18n_railtie.rb +16 -5
  114. data/lib/active_support/inflector/inflections.rb +2 -7
  115. data/lib/active_support/inflector/methods.rb +50 -57
  116. data/lib/active_support/inflector/transliterate.rb +47 -18
  117. data/lib/active_support/json/decoding.rb +25 -26
  118. data/lib/active_support/json/encoding.rb +11 -3
  119. data/lib/active_support/key_generator.rb +1 -33
  120. data/lib/active_support/lazy_load_hooks.rb +5 -2
  121. data/lib/active_support/locale/en.rb +33 -0
  122. data/lib/active_support/locale/en.yml +7 -3
  123. data/lib/active_support/log_subscriber.rb +39 -9
  124. data/lib/active_support/logger.rb +2 -17
  125. data/lib/active_support/logger_silence.rb +11 -19
  126. data/lib/active_support/logger_thread_safe_level.rb +52 -7
  127. data/lib/active_support/message_encryptor.rb +8 -13
  128. data/lib/active_support/message_verifier.rb +10 -10
  129. data/lib/active_support/messages/metadata.rb +11 -2
  130. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  131. data/lib/active_support/messages/rotator.rb +10 -9
  132. data/lib/active_support/multibyte/chars.rb +10 -68
  133. data/lib/active_support/multibyte/unicode.rb +15 -327
  134. data/lib/active_support/notifications/fanout.rb +116 -16
  135. data/lib/active_support/notifications/instrumenter.rb +71 -9
  136. data/lib/active_support/notifications.rb +72 -8
  137. data/lib/active_support/number_helper/number_converter.rb +5 -6
  138. data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
  139. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
  140. data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
  141. data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -3
  142. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  143. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  144. data/lib/active_support/number_helper/number_to_rounded_converter.rb +8 -7
  145. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  146. data/lib/active_support/number_helper.rb +38 -12
  147. data/lib/active_support/option_merger.rb +22 -3
  148. data/lib/active_support/ordered_hash.rb +1 -1
  149. data/lib/active_support/ordered_options.rb +13 -3
  150. data/lib/active_support/parameter_filter.rb +133 -0
  151. data/lib/active_support/per_thread_registry.rb +1 -1
  152. data/lib/active_support/rails.rb +1 -10
  153. data/lib/active_support/railtie.rb +23 -1
  154. data/lib/active_support/reloader.rb +4 -5
  155. data/lib/active_support/secure_compare_rotator.rb +51 -0
  156. data/lib/active_support/security_utils.rb +19 -12
  157. data/lib/active_support/string_inquirer.rb +4 -3
  158. data/lib/active_support/subscriber.rb +72 -24
  159. data/lib/active_support/tagged_logging.rb +42 -8
  160. data/lib/active_support/test_case.rb +92 -1
  161. data/lib/active_support/testing/assertions.rb +30 -9
  162. data/lib/active_support/testing/deprecation.rb +0 -1
  163. data/lib/active_support/testing/file_fixtures.rb +2 -0
  164. data/lib/active_support/testing/isolation.rb +2 -2
  165. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  166. data/lib/active_support/testing/parallelization/server.rb +78 -0
  167. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  168. data/lib/active_support/testing/parallelization.rb +51 -0
  169. data/lib/active_support/testing/setup_and_teardown.rb +5 -9
  170. data/lib/active_support/testing/stream.rb +1 -2
  171. data/lib/active_support/testing/time_helpers.rb +47 -12
  172. data/lib/active_support/time_with_zone.rb +81 -47
  173. data/lib/active_support/values/time_zone.rb +34 -18
  174. data/lib/active_support/xml_mini/jdom.rb +2 -3
  175. data/lib/active_support/xml_mini/libxml.rb +2 -2
  176. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  177. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  178. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  179. data/lib/active_support/xml_mini/rexml.rb +10 -3
  180. data/lib/active_support/xml_mini.rb +2 -10
  181. data/lib/active_support.rb +14 -1
  182. metadata +57 -30
  183. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
  184. data/lib/active_support/core_ext/hash/compact.rb +0 -29
  185. data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
  186. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  187. data/lib/active_support/core_ext/module/reachable.rb +0 -11
  188. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
  189. data/lib/active_support/core_ext/range/include_range.rb +0 -25
  190. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -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
@@ -63,38 +62,36 @@ module ActiveSupport
63
62
  end
64
63
  end
65
64
 
66
- DELETE_GLOB_LUA = "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end"
67
- private_constant :DELETE_GLOB_LUA
65
+ # The maximum number of entries to receive per SCAN call.
66
+ SCAN_BATCH_SIZE = 1000
67
+ private_constant :SCAN_BATCH_SIZE
68
+
69
+ # Advertise cache versioning support.
70
+ def self.supports_cache_versioning?
71
+ true
72
+ end
68
73
 
69
74
  # Support raw values in the local cache strategy.
70
75
  module LocalCacheWithRaw # :nodoc:
71
76
  private
72
- def read_entry(key, options)
73
- entry = super
74
- if options[:raw] && local_cache && entry
75
- entry = deserialize_entry(entry.value)
76
- end
77
- entry
78
- end
79
-
80
- def write_entry(key, entry, options)
77
+ def write_entry(key, entry, **options)
81
78
  if options[:raw] && local_cache
82
79
  raw_entry = Entry.new(serialize_entry(entry, raw: true))
83
80
  raw_entry.expires_at = entry.expires_at
84
- super(key, raw_entry, options)
81
+ super(key, raw_entry, **options)
85
82
  else
86
83
  super
87
84
  end
88
85
  end
89
86
 
90
- def write_multi_entries(entries, options)
87
+ def write_multi_entries(entries, **options)
91
88
  if options[:raw] && local_cache
92
89
  raw_entries = entries.map do |key, entry|
93
90
  raw_entry = Entry.new(serialize_entry(entry, raw: true))
94
91
  raw_entry.expires_at = entry.expires_at
95
92
  end.to_h
96
93
 
97
- super(raw_entries, options)
94
+ super(raw_entries, **options)
98
95
  else
99
96
  super
100
97
  end
@@ -147,15 +144,17 @@ module ActiveSupport
147
144
 
148
145
  # Creates a new Redis cache store.
149
146
  #
150
- # Handles three options: block provided to instantiate, single URL
151
- # provided, and multiple URLs provided.
147
+ # Handles four options: :redis block, :redis instance, single :url
148
+ # string, and multiple :url strings.
152
149
  #
153
- # :redis Proc -> options[:redis].call
154
- # :url String -> Redis.new(url: …)
155
- # :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: … }, …])
156
155
  #
157
156
  # No namespace is set by default. Provide one if the Redis cache
158
- # server is shared with other apps: <tt>namespace: 'myapp-cache'<tt>.
157
+ # server is shared with other apps: <tt>namespace: 'myapp-cache'</tt>.
159
158
  #
160
159
  # Compression is enabled by default with a 1kB threshold, so cached
161
160
  # values larger than 1kB are automatically compressed. Disable by
@@ -170,7 +169,7 @@ module ActiveSupport
170
169
  # Race condition TTL is not set by default. This can be used to avoid
171
170
  # "thundering herd" cache writes when hot cache entries are expired.
172
171
  # See <tt>ActiveSupport::Cache::Store#fetch</tt> for more.
173
- 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)
174
173
  @redis_options = redis_options
175
174
 
176
175
  @max_key_bytesize = MAX_KEY_BYTESIZE
@@ -178,7 +177,8 @@ module ActiveSupport
178
177
 
179
178
  super namespace: namespace,
180
179
  compress: compress, compress_threshold: compress_threshold,
181
- expires_in: expires_in, race_condition_ttl: race_condition_ttl
180
+ expires_in: expires_in, race_condition_ttl: race_condition_ttl,
181
+ coder: coder
182
182
  end
183
183
 
184
184
  def redis
@@ -196,7 +196,7 @@ module ActiveSupport
196
196
 
197
197
  def inspect
198
198
  instance = @redis || @redis_options
199
- "<##{self.class} options=#{options.inspect} redis=#{instance.inspect}>"
199
+ "#<#{self.class} options=#{options.inspect} redis=#{instance.inspect}>"
200
200
  end
201
201
 
202
202
  # Cache Store API implementation.
@@ -232,12 +232,22 @@ module ActiveSupport
232
232
  # Failsafe: Raises errors.
233
233
  def delete_matched(matcher, options = nil)
234
234
  instrument :delete_matched, matcher do
235
- case matcher
236
- when String
237
- redis.with { |c| c.eval DELETE_GLOB_LUA, [], [namespace_key(matcher, options)] }
238
- else
235
+ unless String === matcher
239
236
  raise ArgumentError, "Only Redis glob strings are supported: #{matcher.inspect}"
240
237
  end
238
+ redis.with do |c|
239
+ pattern = namespace_key(matcher, options)
240
+ cursor = "0"
241
+ # Fetch keys in batches using SCAN to avoid blocking the Redis server.
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
250
+ end
241
251
  end
242
252
  end
243
253
 
@@ -252,7 +262,14 @@ module ActiveSupport
252
262
  def increment(name, amount = 1, options = nil)
253
263
  instrument :increment, name, amount: amount do
254
264
  failsafe :increment do
255
- 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
256
273
  end
257
274
  end
258
275
  end
@@ -268,7 +285,14 @@ module ActiveSupport
268
285
  def decrement(name, amount = 1, options = nil)
269
286
  instrument :decrement, name, amount: amount do
270
287
  failsafe :decrement do
271
- 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
272
296
  end
273
297
  end
274
298
  end
@@ -287,7 +311,7 @@ module ActiveSupport
287
311
  # Failsafe: Raises errors.
288
312
  def clear(options = nil)
289
313
  failsafe :clear do
290
- if namespace = merged_options(options)[namespace]
314
+ if namespace = merged_options(options)[:namespace]
291
315
  delete_matched "*", namespace: namespace
292
316
  else
293
317
  redis.with { |c| c.flushdb }
@@ -319,15 +343,16 @@ module ActiveSupport
319
343
 
320
344
  # Store provider interface:
321
345
  # Read an entry from the cache.
322
- def read_entry(key, options = nil)
346
+ def read_entry(key, **options)
323
347
  failsafe :read_entry do
324
- deserialize_entry redis.with { |c| c.get(key) }
348
+ raw = options&.fetch(:raw, false)
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,6 +361,8 @@ module ActiveSupport
336
361
  def read_multi_mget(*names)
337
362
  options = names.extract_options!
338
363
  options = merged_options(options)
364
+ return {} if names == []
365
+ raw = options&.fetch(:raw, false)
339
366
 
340
367
  keys = names.map { |name| normalize_key(name, options) }
341
368
 
@@ -345,7 +372,7 @@ module ActiveSupport
345
372
 
346
373
  names.zip(values).each_with_object({}) do |(name, value), results|
347
374
  if value
348
- entry = deserialize_entry(value)
375
+ entry = deserialize_entry(value, raw: raw)
349
376
  unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(name, options))
350
377
  results[name] = entry.value
351
378
  end
@@ -372,13 +399,19 @@ module ActiveSupport
372
399
  modifiers[:nx] = unless_exist
373
400
  modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in
374
401
 
375
- redis.with { |c| c.set key, serialized_entry, modifiers }
402
+ redis.with { |c| c.set key, serialized_entry, **modifiers }
376
403
  else
377
404
  redis.with { |c| c.set key, serialized_entry }
378
405
  end
379
406
  end
380
407
  end
381
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
+
382
415
  # Delete an entry from the cache.
383
416
  def delete_entry(key, options)
384
417
  failsafe :delete_entry, returning: false do
@@ -386,6 +419,11 @@ module ActiveSupport
386
419
  end
387
420
  end
388
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
+
389
427
  # Nonstandard store provider API to write multiple values at once.
390
428
  def write_multi_entries(entries, expires_in: nil, **options)
391
429
  if entries.any?
@@ -401,11 +439,11 @@ module ActiveSupport
401
439
 
402
440
  # Truncate keys that exceed 1kB.
403
441
  def normalize_key(key, options)
404
- truncate_key super.b
442
+ truncate_key super&.b
405
443
  end
406
444
 
407
445
  def truncate_key(key)
408
- if key.bytesize > max_key_bytesize
446
+ if key && key.bytesize > max_key_bytesize
409
447
  suffix = ":sha2:#{::Digest::SHA2.hexdigest(key)}"
410
448
  truncate_at = max_key_bytesize - suffix.bytesize
411
449
  "#{key.byteslice(0, truncate_at)}#{suffix}"
@@ -414,10 +452,11 @@ module ActiveSupport
414
452
  end
415
453
  end
416
454
 
417
- def deserialize_entry(serialized_entry)
418
- if serialized_entry
419
- entry = Marshal.load(serialized_entry) rescue serialized_entry
420
- 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)
421
460
  end
422
461
  end
423
462
 
@@ -425,7 +464,7 @@ module ActiveSupport
425
464
  if raw
426
465
  entry.value.to_s
427
466
  else
428
- Marshal.dump(entry)
467
+ super(entry)
429
468
  end
430
469
  end
431
470
 
@@ -437,7 +476,7 @@ module ActiveSupport
437
476
 
438
477
  def failsafe(method, returning: nil)
439
478
  yield
440
- rescue ::Redis::BaseConnectionError => e
479
+ rescue ::Redis::BaseError => e
441
480
  handle_exception exception: e, method: method, returning: returning
442
481
  returning
443
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