activesupport 6.0.3.7 → 7.0.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 (204) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +220 -533
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_support/actionable_error.rb +1 -1
  6. data/lib/active_support/array_inquirer.rb +2 -2
  7. data/lib/active_support/backtrace_cleaner.rb +3 -3
  8. data/lib/active_support/benchmarkable.rb +3 -3
  9. data/lib/active_support/cache/file_store.rb +18 -11
  10. data/lib/active_support/cache/mem_cache_store.rb +143 -37
  11. data/lib/active_support/cache/memory_store.rb +56 -28
  12. data/lib/active_support/cache/null_store.rb +10 -2
  13. data/lib/active_support/cache/redis_cache_store.rb +63 -88
  14. data/lib/active_support/cache/strategy/local_cache.rb +46 -57
  15. data/lib/active_support/cache.rb +273 -82
  16. data/lib/active_support/callbacks.rb +226 -118
  17. data/lib/active_support/code_generator.rb +65 -0
  18. data/lib/active_support/concern.rb +49 -5
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
  20. data/lib/active_support/concurrency/share_lock.rb +2 -2
  21. data/lib/active_support/configurable.rb +9 -6
  22. data/lib/active_support/configuration_file.rb +51 -0
  23. data/lib/active_support/core_ext/array/access.rb +1 -5
  24. data/lib/active_support/core_ext/array/conversions.rb +9 -7
  25. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  27. data/lib/active_support/core_ext/array.rb +1 -0
  28. data/lib/active_support/core_ext/benchmark.rb +2 -2
  29. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  30. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  31. data/lib/active_support/core_ext/class/subclasses.rb +21 -40
  32. data/lib/active_support/core_ext/date/blank.rb +1 -1
  33. data/lib/active_support/core_ext/date/calculations.rb +4 -4
  34. data/lib/active_support/core_ext/date/conversions.rb +5 -4
  35. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  36. data/lib/active_support/core_ext/date.rb +1 -0
  37. data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
  38. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  39. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  40. data/lib/active_support/core_ext/date_time/conversions.rb +5 -5
  41. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  42. data/lib/active_support/core_ext/date_time.rb +1 -0
  43. data/lib/active_support/core_ext/digest/uuid.rb +39 -13
  44. data/lib/active_support/core_ext/enumerable.rb +139 -15
  45. data/lib/active_support/core_ext/file/atomic.rb +1 -1
  46. data/lib/active_support/core_ext/hash/conversions.rb +2 -2
  47. data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
  48. data/lib/active_support/core_ext/hash/except.rb +1 -1
  49. data/lib/active_support/core_ext/hash/keys.rb +2 -2
  50. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  51. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  52. data/lib/active_support/core_ext/load_error.rb +1 -1
  53. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  54. data/lib/active_support/core_ext/module/attribute_accessors.rb +25 -29
  55. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +26 -13
  56. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  57. data/lib/active_support/core_ext/module/delegation.rb +40 -36
  58. data/lib/active_support/core_ext/module/introspection.rb +1 -25
  59. data/lib/active_support/core_ext/name_error.rb +23 -2
  60. data/lib/active_support/core_ext/numeric/conversions.rb +79 -72
  61. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  62. data/lib/active_support/core_ext/numeric.rb +1 -0
  63. data/lib/active_support/core_ext/object/blank.rb +2 -2
  64. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  65. data/lib/active_support/core_ext/object/duplicable.rb +11 -0
  66. data/lib/active_support/core_ext/object/json.rb +42 -26
  67. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  68. data/lib/active_support/core_ext/object/try.rb +20 -20
  69. data/lib/active_support/core_ext/object/with_options.rb +20 -1
  70. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  71. data/lib/active_support/core_ext/pathname.rb +3 -0
  72. data/lib/active_support/core_ext/range/compare_range.rb +6 -25
  73. data/lib/active_support/core_ext/range/conversions.rb +8 -8
  74. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  75. data/lib/active_support/core_ext/range/each.rb +1 -1
  76. data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -20
  77. data/lib/active_support/core_ext/range.rb +1 -1
  78. data/lib/active_support/core_ext/regexp.rb +8 -1
  79. data/lib/active_support/core_ext/string/access.rb +5 -24
  80. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  81. data/lib/active_support/core_ext/string/filters.rb +1 -1
  82. data/lib/active_support/core_ext/string/inflections.rb +39 -5
  83. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  84. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  85. data/lib/active_support/core_ext/string/output_safety.rb +69 -45
  86. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  87. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  88. data/lib/active_support/core_ext/symbol.rb +3 -0
  89. data/lib/active_support/core_ext/time/calculations.rb +26 -6
  90. data/lib/active_support/core_ext/time/conversions.rb +6 -3
  91. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  92. data/lib/active_support/core_ext/time/zones.rb +4 -19
  93. data/lib/active_support/core_ext/time.rb +1 -0
  94. data/lib/active_support/core_ext/uri.rb +3 -23
  95. data/lib/active_support/core_ext.rb +2 -1
  96. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  97. data/lib/active_support/current_attributes.rb +39 -16
  98. data/lib/active_support/dependencies/interlock.rb +10 -18
  99. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  100. data/lib/active_support/dependencies.rb +58 -764
  101. data/lib/active_support/deprecation/behaviors.rb +19 -3
  102. data/lib/active_support/deprecation/disallowed.rb +56 -0
  103. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  104. data/lib/active_support/deprecation/method_wrappers.rb +6 -5
  105. data/lib/active_support/deprecation/proxy_wrappers.rb +4 -4
  106. data/lib/active_support/deprecation/reporting.rb +50 -7
  107. data/lib/active_support/deprecation.rb +6 -1
  108. data/lib/active_support/descendants_tracker.rb +177 -64
  109. data/lib/active_support/digest.rb +5 -3
  110. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  111. data/lib/active_support/duration/iso8601_serializer.rb +24 -10
  112. data/lib/active_support/duration.rb +134 -55
  113. data/lib/active_support/encrypted_configuration.rb +11 -1
  114. data/lib/active_support/encrypted_file.rb +20 -3
  115. data/lib/active_support/environment_inquirer.rb +20 -0
  116. data/lib/active_support/error_reporter.rb +117 -0
  117. data/lib/active_support/evented_file_update_checker.rb +70 -134
  118. data/lib/active_support/execution_context/test_helper.rb +13 -0
  119. data/lib/active_support/execution_context.rb +53 -0
  120. data/lib/active_support/execution_wrapper.rb +30 -4
  121. data/lib/active_support/executor/test_helper.rb +7 -0
  122. data/lib/active_support/fork_tracker.rb +71 -0
  123. data/lib/active_support/gem_version.rb +3 -3
  124. data/lib/active_support/hash_with_indifferent_access.rb +51 -25
  125. data/lib/active_support/html_safe_translation.rb +43 -0
  126. data/lib/active_support/i18n.rb +1 -0
  127. data/lib/active_support/i18n_railtie.rb +14 -19
  128. data/lib/active_support/inflector/inflections.rb +24 -9
  129. data/lib/active_support/inflector/methods.rb +29 -49
  130. data/lib/active_support/inflector/transliterate.rb +4 -4
  131. data/lib/active_support/isolated_execution_state.rb +56 -0
  132. data/lib/active_support/json/decoding.rb +4 -4
  133. data/lib/active_support/json/encoding.rb +8 -4
  134. data/lib/active_support/key_generator.rb +19 -2
  135. data/lib/active_support/locale/en.yml +8 -4
  136. data/lib/active_support/log_subscriber.rb +21 -3
  137. data/lib/active_support/logger.rb +1 -1
  138. data/lib/active_support/logger_silence.rb +2 -26
  139. data/lib/active_support/logger_thread_safe_level.rb +34 -21
  140. data/lib/active_support/message_encryptor.rb +12 -10
  141. data/lib/active_support/message_verifier.rb +50 -18
  142. data/lib/active_support/messages/metadata.rb +11 -3
  143. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  144. data/lib/active_support/messages/rotator.rb +6 -5
  145. data/lib/active_support/multibyte/chars.rb +13 -52
  146. data/lib/active_support/multibyte/unicode.rb +1 -87
  147. data/lib/active_support/multibyte.rb +1 -1
  148. data/lib/active_support/notifications/fanout.rb +110 -69
  149. data/lib/active_support/notifications/instrumenter.rb +37 -29
  150. data/lib/active_support/notifications.rb +47 -26
  151. data/lib/active_support/number_helper/number_converter.rb +2 -4
  152. data/lib/active_support/number_helper/number_to_currency_converter.rb +10 -9
  153. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  154. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
  155. data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -2
  156. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
  157. data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
  158. data/lib/active_support/number_helper/rounding_helper.rb +12 -32
  159. data/lib/active_support/number_helper.rb +29 -16
  160. data/lib/active_support/option_merger.rb +9 -16
  161. data/lib/active_support/ordered_hash.rb +1 -1
  162. data/lib/active_support/ordered_options.rb +8 -2
  163. data/lib/active_support/parameter_filter.rb +21 -11
  164. data/lib/active_support/per_thread_registry.rb +6 -1
  165. data/lib/active_support/rails.rb +1 -4
  166. data/lib/active_support/railtie.rb +77 -5
  167. data/lib/active_support/rescuable.rb +6 -6
  168. data/lib/active_support/ruby_features.rb +7 -0
  169. data/lib/active_support/secure_compare_rotator.rb +51 -0
  170. data/lib/active_support/security_utils.rb +19 -12
  171. data/lib/active_support/string_inquirer.rb +2 -2
  172. data/lib/active_support/subscriber.rb +19 -25
  173. data/lib/active_support/tagged_logging.rb +31 -6
  174. data/lib/active_support/test_case.rb +9 -21
  175. data/lib/active_support/testing/assertions.rb +49 -12
  176. data/lib/active_support/testing/deprecation.rb +52 -1
  177. data/lib/active_support/testing/isolation.rb +2 -2
  178. data/lib/active_support/testing/method_call_assertions.rb +5 -5
  179. data/lib/active_support/testing/parallelization/server.rb +82 -0
  180. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  181. data/lib/active_support/testing/parallelization.rb +16 -95
  182. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  183. data/lib/active_support/testing/stream.rb +3 -5
  184. data/lib/active_support/testing/tagged_logging.rb +1 -1
  185. data/lib/active_support/testing/time_helpers.rb +53 -5
  186. data/lib/active_support/time_with_zone.rb +120 -55
  187. data/lib/active_support/values/time_zone.rb +49 -18
  188. data/lib/active_support/xml_mini/jdom.rb +1 -1
  189. data/lib/active_support/xml_mini/libxml.rb +5 -5
  190. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  191. data/lib/active_support/xml_mini/nokogiri.rb +4 -4
  192. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  193. data/lib/active_support/xml_mini/rexml.rb +9 -2
  194. data/lib/active_support/xml_mini.rb +5 -4
  195. data/lib/active_support.rb +29 -1
  196. metadata +46 -45
  197. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  198. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  199. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  200. data/lib/active_support/core_ext/marshal.rb +0 -24
  201. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  202. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  203. data/lib/active_support/core_ext/range/include_range.rb +0 -9
  204. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -15,8 +15,7 @@ begin
15
15
  rescue LoadError
16
16
  end
17
17
 
18
- require "digest/sha2"
19
- require "active_support/core_ext/marshal"
18
+ require "active_support/digest"
20
19
 
21
20
  module ActiveSupport
22
21
  module Cache
@@ -46,7 +45,7 @@ module ActiveSupport
46
45
  # 4.0.1+ for distributed mget support.
47
46
  # * +delete_matched+ support for Redis KEYS globs.
48
47
  class RedisCacheStore < Store
49
- # Keys are truncated with their own SHA2 digest if they exceed 1kB
48
+ # Keys are truncated with the ActiveSupport digest if they exceed 1kB
50
49
  MAX_KEY_BYTESIZE = 1024
51
50
 
52
51
  DEFAULT_REDIS_OPTIONS = {
@@ -71,35 +70,7 @@ module ActiveSupport
71
70
  true
72
71
  end
73
72
 
74
- # Support raw values in the local cache strategy.
75
- module LocalCacheWithRaw # :nodoc:
76
- private
77
- def write_entry(key, entry, **options)
78
- if options[:raw] && local_cache
79
- raw_entry = Entry.new(serialize_entry(entry, raw: true))
80
- raw_entry.expires_at = entry.expires_at
81
- super(key, raw_entry, **options)
82
- else
83
- super
84
- end
85
- end
86
-
87
- def write_multi_entries(entries, **options)
88
- if options[:raw] && local_cache
89
- raw_entries = entries.map do |key, entry|
90
- raw_entry = Entry.new(serialize_entry(entry, raw: true))
91
- raw_entry.expires_at = entry.expires_at
92
- end.to_h
93
-
94
- super(raw_entries, **options)
95
- else
96
- super
97
- end
98
- end
99
- end
100
-
101
73
  prepend Strategy::LocalCache
102
- prepend LocalCacheWithRaw
103
74
 
104
75
  class << self
105
76
  # Factory method to create a new Redis instance.
@@ -113,7 +84,7 @@ module ActiveSupport
113
84
  # :url String -> Redis.new(url: …)
114
85
  # :url Array -> Redis::Distributed.new([{ url: … }, { url: … }, …])
115
86
  #
116
- def build_redis(redis: nil, url: nil, **redis_options) #:nodoc:
87
+ def build_redis(redis: nil, url: nil, **redis_options) # :nodoc:
117
88
  urls = Array(url)
118
89
 
119
90
  if redis.is_a?(Proc)
@@ -169,7 +140,7 @@ module ActiveSupport
169
140
  # Race condition TTL is not set by default. This can be used to avoid
170
141
  # "thundering herd" cache writes when hot cache entries are expired.
171
142
  # See <tt>ActiveSupport::Cache::Store#fetch</tt> for more.
172
- def initialize(namespace: nil, compress: true, compress_threshold: 1.kilobyte, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
143
+ 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)
173
144
  @redis_options = redis_options
174
145
 
175
146
  @max_key_bytesize = MAX_KEY_BYTESIZE
@@ -177,7 +148,8 @@ module ActiveSupport
177
148
 
178
149
  super namespace: namespace,
179
150
  compress: compress, compress_threshold: compress_threshold,
180
- expires_in: expires_in, race_condition_ttl: race_condition_ttl
151
+ expires_in: expires_in, race_condition_ttl: race_condition_ttl,
152
+ coder: coder
181
153
  end
182
154
 
183
155
  def redis
@@ -195,7 +167,7 @@ module ActiveSupport
195
167
 
196
168
  def inspect
197
169
  instance = @redis || @redis_options
198
- "<##{self.class} options=#{options.inspect} redis=#{instance.inspect}>"
170
+ "#<#{self.class} options=#{options.inspect} redis=#{instance.inspect}>"
199
171
  end
200
172
 
201
173
  # Cache Store API implementation.
@@ -238,10 +210,14 @@ module ActiveSupport
238
210
  pattern = namespace_key(matcher, options)
239
211
  cursor = "0"
240
212
  # Fetch keys in batches using SCAN to avoid blocking the Redis server.
241
- begin
242
- cursor, keys = c.scan(cursor, match: pattern, count: SCAN_BATCH_SIZE)
243
- c.del(*keys) unless keys.empty?
244
- end until cursor == "0"
213
+ nodes = c.respond_to?(:nodes) ? c.nodes : [c]
214
+
215
+ nodes.each do |node|
216
+ begin
217
+ cursor, keys = node.scan(cursor, match: pattern, count: SCAN_BATCH_SIZE)
218
+ node.del(*keys) unless keys.empty?
219
+ end until cursor == "0"
220
+ end
245
221
  end
246
222
  end
247
223
  end
@@ -314,12 +290,17 @@ module ActiveSupport
314
290
  end
315
291
  end
316
292
 
317
- def mget_capable? #:nodoc:
293
+ # Get info from redis servers.
294
+ def stats
295
+ redis.with { |c| c.info }
296
+ end
297
+
298
+ def mget_capable? # :nodoc:
318
299
  set_redis_capabilities unless defined? @mget_capable
319
300
  @mget_capable
320
301
  end
321
302
 
322
- def mset_capable? #:nodoc:
303
+ def mset_capable? # :nodoc:
323
304
  set_redis_capabilities unless defined? @mset_capable
324
305
  @mset_capable
325
306
  end
@@ -339,15 +320,18 @@ module ActiveSupport
339
320
  # Store provider interface:
340
321
  # Read an entry from the cache.
341
322
  def read_entry(key, **options)
323
+ deserialize_entry(read_serialized_entry(key, **options), **options)
324
+ end
325
+
326
+ def read_serialized_entry(key, raw: false, **options)
342
327
  failsafe :read_entry do
343
- raw = options&.fetch(:raw, false)
344
- deserialize_entry(redis.with { |c| c.get(key) }, raw: raw)
328
+ redis.with { |c| c.get(key) }
345
329
  end
346
330
  end
347
331
 
348
332
  def read_multi_entries(names, **options)
349
333
  if mget_capable?
350
- read_multi_mget(*names)
334
+ read_multi_mget(*names, **options)
351
335
  else
352
336
  super
353
337
  end
@@ -378,9 +362,11 @@ module ActiveSupport
378
362
  # Write an entry to the cache.
379
363
  #
380
364
  # Requires Redis 2.6.12+ for extended SET options.
381
- def write_entry(key, entry, unless_exist: false, raw: false, expires_in: nil, race_condition_ttl: nil, **options)
382
- serialized_entry = serialize_entry(entry, raw: raw)
365
+ def write_entry(key, entry, raw: false, **options)
366
+ write_serialized_entry(key, serialize_entry(entry, raw: raw, **options), raw: raw, **options)
367
+ end
383
368
 
369
+ def write_serialized_entry(key, payload, raw: false, unless_exist: false, expires_in: nil, race_condition_ttl: nil, **options)
384
370
  # If race condition TTL is in use, ensure that cache entries
385
371
  # stick around a bit longer after they would have expired
386
372
  # so we can purposefully serve stale entries.
@@ -388,16 +374,14 @@ module ActiveSupport
388
374
  expires_in += 5.minutes
389
375
  end
390
376
 
391
- failsafe :write_entry, returning: false do
392
- if unless_exist || expires_in
393
- modifiers = {}
394
- modifiers[:nx] = unless_exist
395
- modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in
377
+ modifiers = {}
378
+ if unless_exist || expires_in
379
+ modifiers[:nx] = unless_exist
380
+ modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in
381
+ end
396
382
 
397
- redis.with { |c| c.set key, serialized_entry, modifiers }
398
- else
399
- redis.with { |c| c.set key, serialized_entry }
400
- end
383
+ failsafe :write_entry, returning: false do
384
+ redis.with { |c| c.set key, payload, **modifiers }
401
385
  end
402
386
  end
403
387
 
@@ -414,12 +398,20 @@ module ActiveSupport
414
398
  end
415
399
  end
416
400
 
401
+ # Deletes multiple entries in the cache. Returns the number of entries deleted.
402
+ def delete_multi_entries(entries, **_options)
403
+ redis.with { |c| c.del(entries) }
404
+ end
405
+
417
406
  # Nonstandard store provider API to write multiple values at once.
418
407
  def write_multi_entries(entries, expires_in: nil, **options)
419
408
  if entries.any?
420
409
  if mset_capable? && expires_in.nil?
421
410
  failsafe :write_multi_entries do
422
- redis.with { |c| c.mapped_mset(serialize_entries(entries, raw: options[:raw])) }
411
+ payload = serialize_entries(entries, **options)
412
+ redis.with do |c|
413
+ c.mapped_mset(payload)
414
+ end
423
415
  end
424
416
  else
425
417
  super
@@ -429,12 +421,12 @@ module ActiveSupport
429
421
 
430
422
  # Truncate keys that exceed 1kB.
431
423
  def normalize_key(key, options)
432
- truncate_key super.b
424
+ truncate_key super&.b
433
425
  end
434
426
 
435
427
  def truncate_key(key)
436
- if key.bytesize > max_key_bytesize
437
- suffix = ":sha2:#{::Digest::SHA2.hexdigest(key)}"
428
+ if key && key.bytesize > max_key_bytesize
429
+ suffix = ":hash:#{ActiveSupport::Digest.hexdigest(key)}"
438
430
  truncate_at = max_key_bytesize - suffix.bytesize
439
431
  "#{key.byteslice(0, truncate_at)}#{suffix}"
440
432
  else
@@ -442,52 +434,35 @@ module ActiveSupport
442
434
  end
443
435
  end
444
436
 
445
- def deserialize_entry(serialized_entry, raw:)
446
- if serialized_entry
447
- entry = Marshal.load(serialized_entry) rescue serialized_entry
448
-
449
- written_raw = serialized_entry.equal?(entry)
450
- if raw != written_raw
451
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
452
- Using a different value for the raw option when reading and writing
453
- to a cache key is deprecated for :redis_cache_store and Rails 6.0
454
- will stop automatically detecting the format when reading to avoid
455
- marshal loading untrusted raw strings.
456
- MSG
457
- end
458
-
459
- entry.is_a?(Entry) ? entry : Entry.new(entry)
437
+ def deserialize_entry(payload, raw: false, **)
438
+ if raw && !payload.nil?
439
+ Entry.new(payload)
440
+ else
441
+ super(payload)
460
442
  end
461
443
  end
462
444
 
463
- def serialize_entry(entry, raw: false)
445
+ def serialize_entry(entry, raw: false, **options)
464
446
  if raw
465
447
  entry.value.to_s
466
448
  else
467
- Marshal.dump(entry)
449
+ super(entry, raw: raw, **options)
468
450
  end
469
451
  end
470
452
 
471
- def serialize_entries(entries, raw: false)
453
+ def serialize_entries(entries, **options)
472
454
  entries.transform_values do |entry|
473
- serialize_entry entry, raw: raw
455
+ serialize_entry(entry, **options)
474
456
  end
475
457
  end
476
458
 
477
459
  def failsafe(method, returning: nil)
478
460
  yield
479
- rescue ::Redis::BaseError => e
480
- handle_exception exception: e, method: method, returning: returning
461
+ rescue ::Redis::BaseError => error
462
+ ActiveSupport.error_reporter&.report(error, handled: true, severity: :warning)
463
+ @error_handler&.call(method: method, exception: error, returning: returning)
481
464
  returning
482
465
  end
483
-
484
- def handle_exception(exception:, method:, returning:)
485
- if @error_handler
486
- @error_handler.(method: method, exception: exception, returning: returning)
487
- end
488
- rescue => failsafe
489
- warn "RedisCacheStore ignored exception in handle_exception: #{failsafe.class}: #{failsafe.message}\n #{failsafe.backtrace.join("\n ")}"
490
- end
491
466
  end
492
467
  end
493
468
  end
@@ -1,8 +1,6 @@
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
- require "active_support/per_thread_registry"
6
4
 
7
5
  module ActiveSupport
8
6
  module Cache
@@ -14,74 +12,56 @@ module ActiveSupport
14
12
  autoload :Middleware, "active_support/cache/strategy/local_cache_middleware"
15
13
 
16
14
  # Class for storing and registering the local caches.
17
- class LocalCacheRegistry # :nodoc:
18
- extend ActiveSupport::PerThreadRegistry
19
-
20
- def initialize
21
- @registry = {}
22
- end
15
+ module LocalCacheRegistry # :nodoc:
16
+ extend self
23
17
 
24
18
  def cache_for(local_cache_key)
25
- @registry[local_cache_key]
19
+ registry = ActiveSupport::IsolatedExecutionState[:active_support_local_cache_registry] ||= {}
20
+ registry[local_cache_key]
26
21
  end
27
22
 
28
23
  def set_cache_for(local_cache_key, value)
29
- @registry[local_cache_key] = value
24
+ registry = ActiveSupport::IsolatedExecutionState[:active_support_local_cache_registry] ||= {}
25
+ registry[local_cache_key] = value
30
26
  end
31
-
32
- def self.set_cache_for(l, v); instance.set_cache_for l, v; end
33
- def self.cache_for(l); instance.cache_for l; end
34
27
  end
35
28
 
36
29
  # Simple memory backed cache. This cache is not thread safe and is intended only
37
30
  # for serving as a temporary memory cache for a single thread.
38
- class LocalStore < Store
31
+ class LocalStore
39
32
  def initialize
40
- super
41
33
  @data = {}
42
34
  end
43
35
 
44
- # Don't allow synchronizing since it isn't thread safe.
45
- def synchronize # :nodoc:
46
- yield
47
- end
48
-
49
36
  def clear(options = nil)
50
37
  @data.clear
51
38
  end
52
39
 
53
- def read_entry(key, **options)
40
+ def read_entry(key)
54
41
  @data[key]
55
42
  end
56
43
 
57
- def read_multi_entries(keys, **options)
58
- values = {}
59
-
60
- keys.each do |name|
61
- entry = read_entry(name, **options)
62
- values[name] = entry.value if entry
63
- end
64
-
65
- values
44
+ def read_multi_entries(keys)
45
+ @data.slice(*keys)
66
46
  end
67
47
 
68
- def write_entry(key, value, **options)
69
- @data[key] = value
48
+ def write_entry(key, entry)
49
+ @data[key] = entry
70
50
  true
71
51
  end
72
52
 
73
- def delete_entry(key, **options)
53
+ def delete_entry(key)
74
54
  !!@data.delete(key)
75
55
  end
76
56
 
77
- def fetch_entry(key, options = nil) # :nodoc:
57
+ def fetch_entry(key) # :nodoc:
78
58
  @data.fetch(key) { @data[key] = yield }
79
59
  end
80
60
  end
81
61
 
82
62
  # Use a local cache for the duration of block.
83
- def with_local_cache
84
- use_temporary_local_cache(LocalStore.new) { yield }
63
+ def with_local_cache(&block)
64
+ use_temporary_local_cache(LocalStore.new, &block)
85
65
  end
86
66
 
87
67
  # Middleware class can be inserted as a Rack handler to be local cache for the
@@ -104,24 +84,36 @@ module ActiveSupport
104
84
  super
105
85
  end
106
86
 
87
+ def delete_matched(matcher, options = nil) # :nodoc:
88
+ return super unless cache = local_cache
89
+ cache.clear
90
+ super
91
+ end
92
+
107
93
  def increment(name, amount = 1, **options) # :nodoc:
108
94
  return super unless local_cache
109
95
  value = bypass_local_cache { super }
110
- write_cache_value(name, value, **options)
96
+ write_cache_value(name, value, raw: true, **options)
111
97
  value
112
98
  end
113
99
 
114
100
  def decrement(name, amount = 1, **options) # :nodoc:
115
101
  return super unless local_cache
116
102
  value = bypass_local_cache { super }
117
- write_cache_value(name, value, **options)
103
+ write_cache_value(name, value, raw: true, **options)
118
104
  value
119
105
  end
120
106
 
121
107
  private
122
- def read_entry(key, **options)
108
+ def read_serialized_entry(key, raw: false, **options)
123
109
  if cache = local_cache
124
- cache.fetch_entry(key) { super }
110
+ hit = true
111
+ entry = cache.fetch_entry(key) do
112
+ hit = false
113
+ super
114
+ end
115
+ options[:event][:store] = cache.class.name if hit && options[:event]
116
+ entry
125
117
  else
126
118
  super
127
119
  end
@@ -130,7 +122,7 @@ module ActiveSupport
130
122
  def read_multi_entries(keys, **options)
131
123
  return super unless local_cache
132
124
 
133
- local_entries = local_cache.read_multi_entries(keys, **options)
125
+ local_entries = local_cache.read_multi_entries(keys)
134
126
  missed_keys = keys - local_entries.keys
135
127
 
136
128
  if missed_keys.any?
@@ -140,30 +132,27 @@ module ActiveSupport
140
132
  end
141
133
  end
142
134
 
143
- def write_entry(key, entry, **options)
144
- if options[:unless_exist]
145
- local_cache.delete_entry(key, **options) if local_cache
135
+ def write_serialized_entry(key, payload, **)
136
+ if return_value = super
137
+ local_cache.write_entry(key, payload) if local_cache
146
138
  else
147
- local_cache.write_entry(key, entry, **options) if local_cache
139
+ local_cache.delete_entry(key) if local_cache
148
140
  end
149
-
150
- super
141
+ return_value
151
142
  end
152
143
 
153
- def delete_entry(key, **options)
154
- local_cache.delete_entry(key, **options) if local_cache
144
+ def delete_entry(key, **)
145
+ local_cache.delete_entry(key) if local_cache
155
146
  super
156
147
  end
157
148
 
158
149
  def write_cache_value(name, value, **options)
159
150
  name = normalize_key(name, options)
160
151
  cache = local_cache
161
- cache.mute do
162
- if value
163
- cache.write(name, value, **options)
164
- else
165
- cache.delete(name, **options)
166
- end
152
+ if value
153
+ cache.write_entry(name, serialize_entry(new_entry(value, **options), **options))
154
+ else
155
+ cache.delete_entry(name)
167
156
  end
168
157
  end
169
158
 
@@ -175,8 +164,8 @@ module ActiveSupport
175
164
  LocalCacheRegistry.cache_for(local_cache_key)
176
165
  end
177
166
 
178
- def bypass_local_cache
179
- use_temporary_local_cache(nil) { yield }
167
+ def bypass_local_cache(&block)
168
+ use_temporary_local_cache(nil, &block)
180
169
  end
181
170
 
182
171
  def use_temporary_local_cache(temporary_cache)