activesupport 6.1.0 → 7.0.4.1

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +263 -352
  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 +0 -2
  7. data/lib/active_support/backtrace_cleaner.rb +2 -2
  8. data/lib/active_support/benchmarkable.rb +2 -2
  9. data/lib/active_support/cache/file_store.rb +16 -10
  10. data/lib/active_support/cache/mem_cache_store.rb +154 -39
  11. data/lib/active_support/cache/memory_store.rb +24 -16
  12. data/lib/active_support/cache/null_store.rb +10 -2
  13. data/lib/active_support/cache/redis_cache_store.rb +59 -78
  14. data/lib/active_support/cache/strategy/local_cache.rb +38 -61
  15. data/lib/active_support/cache.rb +306 -148
  16. data/lib/active_support/callbacks.rb +184 -85
  17. data/lib/active_support/code_generator.rb +65 -0
  18. data/lib/active_support/concern.rb +5 -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 +8 -5
  22. data/lib/active_support/configuration_file.rb +7 -2
  23. data/lib/active_support/core_ext/array/access.rb +1 -5
  24. data/lib/active_support/core_ext/array/conversions.rb +13 -12
  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/inquiry.rb +2 -2
  28. data/lib/active_support/core_ext/array.rb +1 -0
  29. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  30. data/lib/active_support/core_ext/class/subclasses.rb +25 -17
  31. data/lib/active_support/core_ext/date/blank.rb +1 -1
  32. data/lib/active_support/core_ext/date/calculations.rb +9 -9
  33. data/lib/active_support/core_ext/date/conversions.rb +14 -14
  34. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  35. data/lib/active_support/core_ext/date.rb +1 -0
  36. data/lib/active_support/core_ext/date_and_time/calculations.rb +4 -4
  37. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  38. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  39. data/lib/active_support/core_ext/date_time/conversions.rb +13 -13
  40. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  41. data/lib/active_support/core_ext/date_time.rb +1 -0
  42. data/lib/active_support/core_ext/digest/uuid.rb +39 -13
  43. data/lib/active_support/core_ext/enumerable.rb +101 -32
  44. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  45. data/lib/active_support/core_ext/hash/conversions.rb +0 -1
  46. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  47. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  48. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  49. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  50. data/lib/active_support/core_ext/module/attribute_accessors.rb +2 -0
  51. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +19 -10
  52. data/lib/active_support/core_ext/module/delegation.rb +2 -8
  53. data/lib/active_support/core_ext/name_error.rb +2 -8
  54. data/lib/active_support/core_ext/numeric/conversions.rb +80 -77
  55. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  56. data/lib/active_support/core_ext/numeric.rb +1 -0
  57. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  58. data/lib/active_support/core_ext/object/blank.rb +2 -2
  59. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  60. data/lib/active_support/core_ext/object/duplicable.rb +11 -0
  61. data/lib/active_support/core_ext/object/json.rb +37 -25
  62. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  63. data/lib/active_support/core_ext/object/try.rb +20 -20
  64. data/lib/active_support/core_ext/object/with_options.rb +20 -1
  65. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  66. data/lib/active_support/core_ext/pathname.rb +3 -0
  67. data/lib/active_support/core_ext/range/compare_range.rb +0 -25
  68. data/lib/active_support/core_ext/range/conversions.rb +8 -8
  69. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  70. data/lib/active_support/core_ext/range/each.rb +1 -1
  71. data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -25
  72. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  73. data/lib/active_support/core_ext/range.rb +1 -1
  74. data/lib/active_support/core_ext/securerandom.rb +1 -1
  75. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  76. data/lib/active_support/core_ext/string/filters.rb +1 -1
  77. data/lib/active_support/core_ext/string/inflections.rb +1 -1
  78. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  79. data/lib/active_support/core_ext/string/output_safety.rb +91 -39
  80. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
  81. data/lib/active_support/core_ext/time/calculations.rb +9 -7
  82. data/lib/active_support/core_ext/time/conversions.rb +14 -12
  83. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  84. data/lib/active_support/core_ext/time/zones.rb +7 -22
  85. data/lib/active_support/core_ext/time.rb +1 -0
  86. data/lib/active_support/core_ext/uri.rb +3 -27
  87. data/lib/active_support/core_ext.rb +2 -1
  88. data/lib/active_support/current_attributes.rb +32 -14
  89. data/lib/active_support/dependencies/interlock.rb +10 -18
  90. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  91. data/lib/active_support/dependencies.rb +58 -788
  92. data/lib/active_support/deprecation/behaviors.rb +8 -5
  93. data/lib/active_support/deprecation/method_wrappers.rb +3 -3
  94. data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
  95. data/lib/active_support/deprecation.rb +2 -2
  96. data/lib/active_support/descendants_tracker.rb +174 -68
  97. data/lib/active_support/digest.rb +5 -3
  98. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  99. data/lib/active_support/duration/iso8601_serializer.rb +9 -1
  100. data/lib/active_support/duration.rb +81 -51
  101. data/lib/active_support/encrypted_configuration.rb +13 -2
  102. data/lib/active_support/encrypted_file.rb +13 -1
  103. data/lib/active_support/environment_inquirer.rb +1 -1
  104. data/lib/active_support/error_reporter.rb +117 -0
  105. data/lib/active_support/evented_file_update_checker.rb +3 -5
  106. data/lib/active_support/execution_context/test_helper.rb +13 -0
  107. data/lib/active_support/execution_context.rb +53 -0
  108. data/lib/active_support/execution_wrapper.rb +43 -21
  109. data/lib/active_support/executor/test_helper.rb +7 -0
  110. data/lib/active_support/fork_tracker.rb +19 -10
  111. data/lib/active_support/gem_version.rb +5 -5
  112. data/lib/active_support/hash_with_indifferent_access.rb +9 -2
  113. data/lib/active_support/html_safe_translation.rb +43 -0
  114. data/lib/active_support/i18n.rb +1 -0
  115. data/lib/active_support/i18n_railtie.rb +1 -1
  116. data/lib/active_support/inflector/inflections.rb +23 -7
  117. data/lib/active_support/inflector/methods.rb +24 -48
  118. data/lib/active_support/inflector/transliterate.rb +1 -1
  119. data/lib/active_support/isolated_execution_state.rb +72 -0
  120. data/lib/active_support/json/encoding.rb +3 -3
  121. data/lib/active_support/key_generator.rb +22 -5
  122. data/lib/active_support/lazy_load_hooks.rb +28 -4
  123. data/lib/active_support/locale/en.yml +2 -2
  124. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  125. data/lib/active_support/log_subscriber.rb +15 -5
  126. data/lib/active_support/logger_thread_safe_level.rb +4 -13
  127. data/lib/active_support/message_encryptor.rb +12 -6
  128. data/lib/active_support/message_verifier.rb +46 -14
  129. data/lib/active_support/messages/metadata.rb +2 -2
  130. data/lib/active_support/multibyte/chars.rb +10 -11
  131. data/lib/active_support/multibyte/unicode.rb +0 -12
  132. data/lib/active_support/multibyte.rb +1 -1
  133. data/lib/active_support/notifications/fanout.rb +91 -65
  134. data/lib/active_support/notifications/instrumenter.rb +32 -15
  135. data/lib/active_support/notifications.rb +24 -24
  136. data/lib/active_support/number_helper/number_converter.rb +1 -3
  137. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  138. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  139. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  140. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
  141. data/lib/active_support/number_helper/number_to_rounded_converter.rb +10 -6
  142. data/lib/active_support/number_helper/rounding_helper.rb +2 -6
  143. data/lib/active_support/number_helper.rb +0 -2
  144. data/lib/active_support/option_merger.rb +10 -18
  145. data/lib/active_support/ordered_hash.rb +1 -1
  146. data/lib/active_support/ordered_options.rb +1 -1
  147. data/lib/active_support/parameter_filter.rb +6 -1
  148. data/lib/active_support/per_thread_registry.rb +5 -0
  149. data/lib/active_support/railtie.rb +69 -19
  150. data/lib/active_support/reloader.rb +1 -1
  151. data/lib/active_support/rescuable.rb +16 -16
  152. data/lib/active_support/ruby_features.rb +7 -0
  153. data/lib/active_support/secure_compare_rotator.rb +2 -2
  154. data/lib/active_support/security_utils.rb +1 -1
  155. data/lib/active_support/string_inquirer.rb +0 -2
  156. data/lib/active_support/subscriber.rb +7 -18
  157. data/lib/active_support/tagged_logging.rb +2 -2
  158. data/lib/active_support/test_case.rb +13 -21
  159. data/lib/active_support/testing/assertions.rb +36 -6
  160. data/lib/active_support/testing/deprecation.rb +52 -1
  161. data/lib/active_support/testing/isolation.rb +2 -2
  162. data/lib/active_support/testing/method_call_assertions.rb +5 -5
  163. data/lib/active_support/testing/parallelization/server.rb +4 -0
  164. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  165. data/lib/active_support/testing/parallelization.rb +4 -0
  166. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  167. data/lib/active_support/testing/stream.rb +3 -5
  168. data/lib/active_support/testing/tagged_logging.rb +1 -1
  169. data/lib/active_support/testing/time_helpers.rb +13 -2
  170. data/lib/active_support/time_with_zone.rb +60 -20
  171. data/lib/active_support/values/time_zone.rb +36 -15
  172. data/lib/active_support/version.rb +1 -1
  173. data/lib/active_support/xml_mini/jdom.rb +1 -1
  174. data/lib/active_support/xml_mini/libxml.rb +5 -5
  175. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  176. data/lib/active_support/xml_mini/nokogiri.rb +4 -4
  177. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  178. data/lib/active_support/xml_mini/rexml.rb +1 -1
  179. data/lib/active_support/xml_mini.rb +5 -4
  180. data/lib/active_support.rb +17 -1
  181. metadata +29 -26
  182. data/lib/active_support/core_ext/marshal.rb +0 -26
  183. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -5,18 +5,21 @@ begin
5
5
  require "redis"
6
6
  require "redis/distributed"
7
7
  rescue LoadError
8
- warn "The Redis cache store requires the redis gem, version 4.0.1 or later. Please add it to your Gemfile: `gem \"redis\", \"~> 4.0\"`"
8
+ warn "The Redis cache store requires the redis gem, version 4.0.1 or later. Please add it to your Gemfile: `gem \"redis\", \">= 4.0.1\"`"
9
9
  raise
10
10
  end
11
11
 
12
12
  # Prefer the hiredis driver but don't require it.
13
13
  begin
14
- require "redis/connection/hiredis"
14
+ if ::Redis::VERSION < "5"
15
+ require "redis/connection/hiredis"
16
+ else
17
+ require "hiredis-client"
18
+ end
15
19
  rescue LoadError
16
20
  end
17
21
 
18
- require "digest/sha2"
19
- require "active_support/core_ext/marshal"
22
+ require "active_support/digest"
20
23
 
21
24
  module ActiveSupport
22
25
  module Cache
@@ -46,7 +49,7 @@ module ActiveSupport
46
49
  # 4.0.1+ for distributed mget support.
47
50
  # * +delete_matched+ support for Redis KEYS globs.
48
51
  class RedisCacheStore < Store
49
- # Keys are truncated with their own SHA2 digest if they exceed 1kB
52
+ # Keys are truncated with the ActiveSupport digest if they exceed 1kB
50
53
  MAX_KEY_BYTESIZE = 1024
51
54
 
52
55
  DEFAULT_REDIS_OPTIONS = {
@@ -71,35 +74,7 @@ module ActiveSupport
71
74
  true
72
75
  end
73
76
 
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
77
  prepend Strategy::LocalCache
102
- prepend LocalCacheWithRaw
103
78
 
104
79
  class << self
105
80
  # Factory method to create a new Redis instance.
@@ -113,7 +88,7 @@ module ActiveSupport
113
88
  # :url String -> Redis.new(url: …)
114
89
  # :url Array -> Redis::Distributed.new([{ url: … }, { url: … }, …])
115
90
  #
116
- def build_redis(redis: nil, url: nil, **redis_options) #:nodoc:
91
+ def build_redis(redis: nil, url: nil, **redis_options) # :nodoc:
117
92
  urls = Array(url)
118
93
 
119
94
  if redis.is_a?(Proc)
@@ -121,9 +96,11 @@ module ActiveSupport
121
96
  elsif redis
122
97
  redis
123
98
  elsif urls.size > 1
124
- build_redis_distributed_client urls: urls, **redis_options
99
+ build_redis_distributed_client(urls: urls, **redis_options)
100
+ elsif urls.empty?
101
+ build_redis_client(**redis_options)
125
102
  else
126
- build_redis_client url: urls.first, **redis_options
103
+ build_redis_client(url: urls.first, **redis_options)
127
104
  end
128
105
  end
129
106
 
@@ -134,8 +111,8 @@ module ActiveSupport
134
111
  end
135
112
  end
136
113
 
137
- def build_redis_client(url:, **redis_options)
138
- ::Redis.new DEFAULT_REDIS_OPTIONS.merge(redis_options.merge(url: url))
114
+ def build_redis_client(**redis_options)
115
+ ::Redis.new(DEFAULT_REDIS_OPTIONS.merge(redis_options))
139
116
  end
140
117
  end
141
118
 
@@ -168,8 +145,8 @@ module ActiveSupport
168
145
  #
169
146
  # Race condition TTL is not set by default. This can be used to avoid
170
147
  # "thundering herd" cache writes when hot cache entries are expired.
171
- # See <tt>ActiveSupport::Cache::Store#fetch</tt> for more.
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)
148
+ # See ActiveSupport::Cache::Store#fetch for more.
149
+ 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
150
  @redis_options = redis_options
174
151
 
175
152
  @max_key_bytesize = MAX_KEY_BYTESIZE
@@ -254,8 +231,8 @@ module ActiveSupport
254
231
  # Cache Store API implementation.
255
232
  #
256
233
  # Increment a cached value. This method uses the Redis incr atomic
257
- # operator and can only be used on values written with the :raw option.
258
- # Calling it on a value not stored with :raw will initialize that value
234
+ # operator and can only be used on values written with the +:raw+ option.
235
+ # Calling it on a value not stored with +:raw+ will initialize that value
259
236
  # to zero.
260
237
  #
261
238
  # Failsafe: Raises errors.
@@ -277,8 +254,8 @@ module ActiveSupport
277
254
  # Cache Store API implementation.
278
255
  #
279
256
  # Decrement a cached value. This method uses the Redis decr atomic
280
- # operator and can only be used on values written with the :raw option.
281
- # Calling it on a value not stored with :raw will initialize that value
257
+ # operator and can only be used on values written with the +:raw+ option.
258
+ # Calling it on a value not stored with +:raw+ will initialize that value
282
259
  # to zero.
283
260
  #
284
261
  # Failsafe: Raises errors.
@@ -319,12 +296,17 @@ module ActiveSupport
319
296
  end
320
297
  end
321
298
 
322
- def mget_capable? #:nodoc:
299
+ # Get info from redis servers.
300
+ def stats
301
+ redis.with { |c| c.info }
302
+ end
303
+
304
+ def mget_capable? # :nodoc:
323
305
  set_redis_capabilities unless defined? @mget_capable
324
306
  @mget_capable
325
307
  end
326
308
 
327
- def mset_capable? #:nodoc:
309
+ def mset_capable? # :nodoc:
328
310
  set_redis_capabilities unless defined? @mset_capable
329
311
  @mset_capable
330
312
  end
@@ -344,9 +326,12 @@ module ActiveSupport
344
326
  # Store provider interface:
345
327
  # Read an entry from the cache.
346
328
  def read_entry(key, **options)
329
+ deserialize_entry(read_serialized_entry(key, **options), **options)
330
+ end
331
+
332
+ def read_serialized_entry(key, raw: false, **options)
347
333
  failsafe :read_entry do
348
- raw = options&.fetch(:raw, false)
349
- deserialize_entry(redis.with { |c| c.get(key) }, raw: raw)
334
+ redis.with { |c| c.get(key) }
350
335
  end
351
336
  end
352
337
 
@@ -383,9 +368,11 @@ module ActiveSupport
383
368
  # Write an entry to the cache.
384
369
  #
385
370
  # Requires Redis 2.6.12+ for extended SET options.
386
- def write_entry(key, entry, unless_exist: false, raw: false, expires_in: nil, race_condition_ttl: nil, **options)
387
- serialized_entry = serialize_entry(entry, raw: raw)
371
+ def write_entry(key, entry, raw: false, **options)
372
+ write_serialized_entry(key, serialize_entry(entry, raw: raw, **options), raw: raw, **options)
373
+ end
388
374
 
375
+ def write_serialized_entry(key, payload, raw: false, unless_exist: false, expires_in: nil, race_condition_ttl: nil, **options)
389
376
  # If race condition TTL is in use, ensure that cache entries
390
377
  # stick around a bit longer after they would have expired
391
378
  # so we can purposefully serve stale entries.
@@ -393,16 +380,14 @@ module ActiveSupport
393
380
  expires_in += 5.minutes
394
381
  end
395
382
 
396
- failsafe :write_entry, returning: false do
397
- if unless_exist || expires_in
398
- modifiers = {}
399
- modifiers[:nx] = unless_exist
400
- modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in
383
+ modifiers = {}
384
+ if unless_exist || expires_in
385
+ modifiers[:nx] = unless_exist
386
+ modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in
387
+ end
401
388
 
402
- redis.with { |c| c.set key, serialized_entry, **modifiers }
403
- else
404
- redis.with { |c| c.set key, serialized_entry }
405
- end
389
+ failsafe :write_entry, returning: false do
390
+ redis.with { |c| c.set key, payload, **modifiers }
406
391
  end
407
392
  end
408
393
 
@@ -429,7 +414,10 @@ module ActiveSupport
429
414
  if entries.any?
430
415
  if mset_capable? && expires_in.nil?
431
416
  failsafe :write_multi_entries do
432
- redis.with { |c| c.mapped_mset(serialize_entries(entries, raw: options[:raw])) }
417
+ payload = serialize_entries(entries, **options)
418
+ redis.with do |c|
419
+ c.mapped_mset(payload)
420
+ end
433
421
  end
434
422
  else
435
423
  super
@@ -444,7 +432,7 @@ module ActiveSupport
444
432
 
445
433
  def truncate_key(key)
446
434
  if key && key.bytesize > max_key_bytesize
447
- suffix = ":sha2:#{::Digest::SHA2.hexdigest(key)}"
435
+ suffix = ":hash:#{ActiveSupport::Digest.hexdigest(key)}"
448
436
  truncate_at = max_key_bytesize - suffix.bytesize
449
437
  "#{key.byteslice(0, truncate_at)}#{suffix}"
450
438
  else
@@ -452,42 +440,35 @@ module ActiveSupport
452
440
  end
453
441
  end
454
442
 
455
- def deserialize_entry(payload, raw:)
456
- if payload && raw
457
- Entry.new(payload, compress: false)
443
+ def deserialize_entry(payload, raw: false, **)
444
+ if raw && !payload.nil?
445
+ Entry.new(payload)
458
446
  else
459
447
  super(payload)
460
448
  end
461
449
  end
462
450
 
463
- def serialize_entry(entry, raw: false)
451
+ def serialize_entry(entry, raw: false, **options)
464
452
  if raw
465
453
  entry.value.to_s
466
454
  else
467
- super(entry)
455
+ super(entry, raw: raw, **options)
468
456
  end
469
457
  end
470
458
 
471
- def serialize_entries(entries, raw: false)
459
+ def serialize_entries(entries, **options)
472
460
  entries.transform_values do |entry|
473
- serialize_entry entry, raw: raw
461
+ serialize_entry(entry, **options)
474
462
  end
475
463
  end
476
464
 
477
465
  def failsafe(method, returning: nil)
478
466
  yield
479
- rescue ::Redis::BaseError => e
480
- handle_exception exception: e, method: method, returning: returning
467
+ rescue ::Redis::BaseError => error
468
+ ActiveSupport.error_reporter&.report(error, handled: true, severity: :warning)
469
+ @error_handler&.call(method: method, exception: error, returning: returning)
481
470
  returning
482
471
  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
472
  end
492
473
  end
493
474
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/string/inflections"
4
- require "active_support/per_thread_registry"
5
4
 
6
5
  module ActiveSupport
7
6
  module Cache
@@ -13,78 +12,56 @@ module ActiveSupport
13
12
  autoload :Middleware, "active_support/cache/strategy/local_cache_middleware"
14
13
 
15
14
  # Class for storing and registering the local caches.
16
- class LocalCacheRegistry # :nodoc:
17
- extend ActiveSupport::PerThreadRegistry
18
-
19
- def initialize
20
- @registry = {}
21
- end
15
+ module LocalCacheRegistry # :nodoc:
16
+ extend self
22
17
 
23
18
  def cache_for(local_cache_key)
24
- @registry[local_cache_key]
19
+ registry = ActiveSupport::IsolatedExecutionState[:active_support_local_cache_registry] ||= {}
20
+ registry[local_cache_key]
25
21
  end
26
22
 
27
23
  def set_cache_for(local_cache_key, value)
28
- @registry[local_cache_key] = value
24
+ registry = ActiveSupport::IsolatedExecutionState[:active_support_local_cache_registry] ||= {}
25
+ registry[local_cache_key] = value
29
26
  end
30
-
31
- def self.set_cache_for(l, v); instance.set_cache_for l, v; end
32
- def self.cache_for(l); instance.cache_for l; end
33
27
  end
34
28
 
35
29
  # Simple memory backed cache. This cache is not thread safe and is intended only
36
30
  # for serving as a temporary memory cache for a single thread.
37
- class LocalStore < Store
31
+ class LocalStore
38
32
  def initialize
39
- super
40
33
  @data = {}
41
34
  end
42
35
 
43
- # Don't allow synchronizing since it isn't thread safe.
44
- def synchronize # :nodoc:
45
- yield
46
- end
47
-
48
36
  def clear(options = nil)
49
37
  @data.clear
50
38
  end
51
39
 
52
- def read_entry(key, **options)
40
+ def read_entry(key)
53
41
  @data[key]
54
42
  end
55
43
 
56
- def read_multi_entries(keys, **options)
57
- values = {}
58
-
59
- keys.each do |name|
60
- entry = read_entry(name, **options)
61
- values[name] = entry.value if entry
62
- end
63
-
64
- values
44
+ def read_multi_entries(keys)
45
+ @data.slice(*keys)
65
46
  end
66
47
 
67
- def write_entry(key, entry, **options)
68
- entry.dup_value!
48
+ def write_entry(key, entry)
69
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:
78
- entry = @data.fetch(key) { @data[key] = yield }
79
- dup_entry = entry.dup
80
- dup_entry&.dup_value!
81
- dup_entry
57
+ def fetch_entry(key) # :nodoc:
58
+ @data.fetch(key) { @data[key] = yield }
82
59
  end
83
60
  end
84
61
 
85
62
  # Use a local cache for the duration of block.
86
- def with_local_cache
87
- use_temporary_local_cache(LocalStore.new) { yield }
63
+ def with_local_cache(&block)
64
+ use_temporary_local_cache(LocalStore.new, &block)
88
65
  end
89
66
 
90
67
  # Middleware class can be inserted as a Rack handler to be local cache for the
@@ -116,27 +93,27 @@ module ActiveSupport
116
93
  def increment(name, amount = 1, **options) # :nodoc:
117
94
  return super unless local_cache
118
95
  value = bypass_local_cache { super }
119
- write_cache_value(name, value, **options)
96
+ write_cache_value(name, value, raw: true, **options)
120
97
  value
121
98
  end
122
99
 
123
100
  def decrement(name, amount = 1, **options) # :nodoc:
124
101
  return super unless local_cache
125
102
  value = bypass_local_cache { super }
126
- write_cache_value(name, value, **options)
103
+ write_cache_value(name, value, raw: true, **options)
127
104
  value
128
105
  end
129
106
 
130
107
  private
131
- def read_entry(key, **options)
108
+ def read_serialized_entry(key, raw: false, **options)
132
109
  if cache = local_cache
133
110
  hit = true
134
- value = cache.fetch_entry(key) do
111
+ entry = cache.fetch_entry(key) do
135
112
  hit = false
136
113
  super
137
114
  end
138
115
  options[:event][:store] = cache.class.name if hit && options[:event]
139
- value
116
+ entry
140
117
  else
141
118
  super
142
119
  end
@@ -145,7 +122,10 @@ module ActiveSupport
145
122
  def read_multi_entries(keys, **options)
146
123
  return super unless local_cache
147
124
 
148
- local_entries = local_cache.read_multi_entries(keys, **options)
125
+ local_entries = local_cache.read_multi_entries(keys)
126
+ local_entries.transform_values! do |payload|
127
+ deserialize_entry(payload).value
128
+ end
149
129
  missed_keys = keys - local_entries.keys
150
130
 
151
131
  if missed_keys.any?
@@ -155,30 +135,27 @@ module ActiveSupport
155
135
  end
156
136
  end
157
137
 
158
- def write_entry(key, entry, **options)
159
- if options[:unless_exist]
160
- local_cache.delete_entry(key, **options) if local_cache
138
+ def write_serialized_entry(key, payload, **)
139
+ if return_value = super
140
+ local_cache.write_entry(key, payload) if local_cache
161
141
  else
162
- local_cache.write_entry(key, entry, **options) if local_cache
142
+ local_cache.delete_entry(key) if local_cache
163
143
  end
164
-
165
- super
144
+ return_value
166
145
  end
167
146
 
168
- def delete_entry(key, **options)
169
- local_cache.delete_entry(key, **options) if local_cache
147
+ def delete_entry(key, **)
148
+ local_cache.delete_entry(key) if local_cache
170
149
  super
171
150
  end
172
151
 
173
152
  def write_cache_value(name, value, **options)
174
153
  name = normalize_key(name, options)
175
154
  cache = local_cache
176
- cache.mute do
177
- if value
178
- cache.write(name, value, options)
179
- else
180
- cache.delete(name, **options)
181
- end
155
+ if value
156
+ cache.write_entry(name, serialize_entry(new_entry(value, **options), **options))
157
+ else
158
+ cache.delete_entry(name)
182
159
  end
183
160
  end
184
161
 
@@ -190,8 +167,8 @@ module ActiveSupport
190
167
  LocalCacheRegistry.cache_for(local_cache_key)
191
168
  end
192
169
 
193
- def bypass_local_cache
194
- use_temporary_local_cache(nil) { yield }
170
+ def bypass_local_cache(&block)
171
+ use_temporary_local_cache(nil, &block)
195
172
  end
196
173
 
197
174
  def use_temporary_local_cache(temporary_cache)