activesupport 6.1.6.1 → 7.0.3.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 (179) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +231 -515
  3. data/lib/active_support/actionable_error.rb +1 -1
  4. data/lib/active_support/array_inquirer.rb +0 -2
  5. data/lib/active_support/backtrace_cleaner.rb +2 -2
  6. data/lib/active_support/benchmarkable.rb +2 -2
  7. data/lib/active_support/cache/file_store.rb +15 -9
  8. data/lib/active_support/cache/mem_cache_store.rb +132 -37
  9. data/lib/active_support/cache/memory_store.rb +24 -16
  10. data/lib/active_support/cache/null_store.rb +10 -2
  11. data/lib/active_support/cache/redis_cache_store.rb +47 -72
  12. data/lib/active_support/cache/strategy/local_cache.rb +38 -61
  13. data/lib/active_support/cache.rb +193 -46
  14. data/lib/active_support/callbacks.rb +184 -85
  15. data/lib/active_support/code_generator.rb +65 -0
  16. data/lib/active_support/concern.rb +5 -5
  17. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
  18. data/lib/active_support/concurrency/share_lock.rb +2 -2
  19. data/lib/active_support/configurable.rb +8 -5
  20. data/lib/active_support/configuration_file.rb +1 -1
  21. data/lib/active_support/core_ext/array/access.rb +1 -5
  22. data/lib/active_support/core_ext/array/conversions.rb +13 -12
  23. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  24. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  25. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  26. data/lib/active_support/core_ext/array.rb +1 -0
  27. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  28. data/lib/active_support/core_ext/class/subclasses.rb +25 -17
  29. data/lib/active_support/core_ext/date/blank.rb +1 -1
  30. data/lib/active_support/core_ext/date/calculations.rb +9 -9
  31. data/lib/active_support/core_ext/date/conversions.rb +14 -14
  32. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  33. data/lib/active_support/core_ext/date.rb +1 -0
  34. data/lib/active_support/core_ext/date_and_time/calculations.rb +4 -4
  35. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  36. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  37. data/lib/active_support/core_ext/date_time/conversions.rb +13 -13
  38. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  39. data/lib/active_support/core_ext/date_time.rb +1 -0
  40. data/lib/active_support/core_ext/digest/uuid.rb +39 -14
  41. data/lib/active_support/core_ext/enumerable.rb +101 -32
  42. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  43. data/lib/active_support/core_ext/hash/conversions.rb +0 -1
  44. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  45. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  46. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  47. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  48. data/lib/active_support/core_ext/module/attribute_accessors.rb +2 -0
  49. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +19 -10
  50. data/lib/active_support/core_ext/module/delegation.rb +2 -8
  51. data/lib/active_support/core_ext/name_error.rb +2 -8
  52. data/lib/active_support/core_ext/numeric/conversions.rb +80 -77
  53. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  54. data/lib/active_support/core_ext/numeric.rb +1 -0
  55. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  56. data/lib/active_support/core_ext/object/blank.rb +2 -2
  57. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  58. data/lib/active_support/core_ext/object/duplicable.rb +11 -0
  59. data/lib/active_support/core_ext/object/json.rb +30 -25
  60. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  61. data/lib/active_support/core_ext/object/try.rb +20 -20
  62. data/lib/active_support/core_ext/object/with_options.rb +20 -1
  63. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  64. data/lib/active_support/core_ext/pathname.rb +3 -0
  65. data/lib/active_support/core_ext/range/compare_range.rb +0 -25
  66. data/lib/active_support/core_ext/range/conversions.rb +8 -8
  67. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  68. data/lib/active_support/core_ext/range/each.rb +1 -1
  69. data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -25
  70. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  71. data/lib/active_support/core_ext/range.rb +1 -1
  72. data/lib/active_support/core_ext/securerandom.rb +1 -1
  73. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  74. data/lib/active_support/core_ext/string/filters.rb +1 -1
  75. data/lib/active_support/core_ext/string/inflections.rb +1 -1
  76. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  77. data/lib/active_support/core_ext/string/output_safety.rb +62 -38
  78. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
  79. data/lib/active_support/core_ext/time/calculations.rb +7 -8
  80. data/lib/active_support/core_ext/time/conversions.rb +13 -12
  81. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  82. data/lib/active_support/core_ext/time/zones.rb +7 -22
  83. data/lib/active_support/core_ext/time.rb +1 -0
  84. data/lib/active_support/core_ext/uri.rb +3 -27
  85. data/lib/active_support/core_ext.rb +1 -0
  86. data/lib/active_support/current_attributes.rb +31 -14
  87. data/lib/active_support/dependencies/interlock.rb +10 -18
  88. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  89. data/lib/active_support/dependencies.rb +58 -788
  90. data/lib/active_support/deprecation/behaviors.rb +5 -2
  91. data/lib/active_support/deprecation/method_wrappers.rb +3 -3
  92. data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
  93. data/lib/active_support/deprecation.rb +2 -2
  94. data/lib/active_support/descendants_tracker.rb +174 -68
  95. data/lib/active_support/digest.rb +4 -4
  96. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  97. data/lib/active_support/duration/iso8601_serializer.rb +9 -1
  98. data/lib/active_support/duration.rb +77 -48
  99. data/lib/active_support/encrypted_configuration.rb +13 -2
  100. data/lib/active_support/encrypted_file.rb +1 -1
  101. data/lib/active_support/environment_inquirer.rb +1 -1
  102. data/lib/active_support/error_reporter.rb +117 -0
  103. data/lib/active_support/evented_file_update_checker.rb +3 -5
  104. data/lib/active_support/execution_context/test_helper.rb +13 -0
  105. data/lib/active_support/execution_context.rb +53 -0
  106. data/lib/active_support/execution_wrapper.rb +30 -11
  107. data/lib/active_support/executor/test_helper.rb +7 -0
  108. data/lib/active_support/fork_tracker.rb +19 -12
  109. data/lib/active_support/gem_version.rb +4 -4
  110. data/lib/active_support/hash_with_indifferent_access.rb +3 -1
  111. data/lib/active_support/html_safe_translation.rb +43 -0
  112. data/lib/active_support/i18n.rb +1 -0
  113. data/lib/active_support/i18n_railtie.rb +1 -1
  114. data/lib/active_support/inflector/inflections.rb +23 -7
  115. data/lib/active_support/inflector/methods.rb +24 -48
  116. data/lib/active_support/inflector/transliterate.rb +1 -1
  117. data/lib/active_support/isolated_execution_state.rb +72 -0
  118. data/lib/active_support/json/encoding.rb +3 -3
  119. data/lib/active_support/key_generator.rb +22 -5
  120. data/lib/active_support/lazy_load_hooks.rb +14 -3
  121. data/lib/active_support/locale/en.yml +1 -1
  122. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  123. data/lib/active_support/log_subscriber.rb +15 -5
  124. data/lib/active_support/logger.rb +4 -5
  125. data/lib/active_support/logger_thread_safe_level.rb +4 -13
  126. data/lib/active_support/message_encryptor.rb +12 -6
  127. data/lib/active_support/message_verifier.rb +46 -14
  128. data/lib/active_support/messages/metadata.rb +2 -2
  129. data/lib/active_support/multibyte/chars.rb +10 -11
  130. data/lib/active_support/multibyte/unicode.rb +0 -12
  131. data/lib/active_support/multibyte.rb +1 -1
  132. data/lib/active_support/notifications/fanout.rb +91 -65
  133. data/lib/active_support/notifications/instrumenter.rb +32 -15
  134. data/lib/active_support/notifications.rb +17 -23
  135. data/lib/active_support/number_helper/number_converter.rb +1 -3
  136. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  137. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  138. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  139. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
  140. data/lib/active_support/number_helper/rounding_helper.rb +1 -5
  141. data/lib/active_support/number_helper.rb +0 -2
  142. data/lib/active_support/option_merger.rb +8 -16
  143. data/lib/active_support/ordered_hash.rb +1 -1
  144. data/lib/active_support/ordered_options.rb +1 -1
  145. data/lib/active_support/parameter_filter.rb +5 -0
  146. data/lib/active_support/per_thread_registry.rb +5 -1
  147. data/lib/active_support/railtie.rb +69 -19
  148. data/lib/active_support/rescuable.rb +4 -4
  149. data/lib/active_support/ruby_features.rb +7 -0
  150. data/lib/active_support/secure_compare_rotator.rb +2 -2
  151. data/lib/active_support/string_inquirer.rb +0 -2
  152. data/lib/active_support/subscriber.rb +7 -18
  153. data/lib/active_support/tagged_logging.rb +16 -1
  154. data/lib/active_support/test_case.rb +9 -21
  155. data/lib/active_support/testing/assertions.rb +35 -5
  156. data/lib/active_support/testing/deprecation.rb +52 -1
  157. data/lib/active_support/testing/isolation.rb +2 -2
  158. data/lib/active_support/testing/method_call_assertions.rb +5 -5
  159. data/lib/active_support/testing/parallelization/server.rb +4 -0
  160. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  161. data/lib/active_support/testing/parallelization.rb +4 -0
  162. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  163. data/lib/active_support/testing/stream.rb +3 -5
  164. data/lib/active_support/testing/tagged_logging.rb +1 -1
  165. data/lib/active_support/testing/time_helpers.rb +13 -2
  166. data/lib/active_support/time_with_zone.rb +58 -17
  167. data/lib/active_support/values/time_zone.rb +33 -14
  168. data/lib/active_support/version.rb +1 -1
  169. data/lib/active_support/xml_mini/jdom.rb +1 -1
  170. data/lib/active_support/xml_mini/libxml.rb +5 -5
  171. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  172. data/lib/active_support/xml_mini/nokogiri.rb +4 -4
  173. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  174. data/lib/active_support/xml_mini/rexml.rb +1 -1
  175. data/lib/active_support/xml_mini.rb +5 -4
  176. data/lib/active_support.rb +16 -0
  177. metadata +23 -21
  178. data/lib/active_support/core_ext/marshal.rb +0 -26
  179. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -120
@@ -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)
@@ -168,8 +139,8 @@ module ActiveSupport
168
139
  #
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
- # 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)
142
+ # See ActiveSupport::Cache::Store#fetch for more.
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
@@ -254,8 +225,8 @@ module ActiveSupport
254
225
  # Cache Store API implementation.
255
226
  #
256
227
  # 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
228
+ # operator and can only be used on values written with the +:raw+ option.
229
+ # Calling it on a value not stored with +:raw+ will initialize that value
259
230
  # to zero.
260
231
  #
261
232
  # Failsafe: Raises errors.
@@ -277,8 +248,8 @@ module ActiveSupport
277
248
  # Cache Store API implementation.
278
249
  #
279
250
  # 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
251
+ # operator and can only be used on values written with the +:raw+ option.
252
+ # Calling it on a value not stored with +:raw+ will initialize that value
282
253
  # to zero.
283
254
  #
284
255
  # Failsafe: Raises errors.
@@ -319,12 +290,17 @@ module ActiveSupport
319
290
  end
320
291
  end
321
292
 
322
- 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:
323
299
  set_redis_capabilities unless defined? @mget_capable
324
300
  @mget_capable
325
301
  end
326
302
 
327
- def mset_capable? #:nodoc:
303
+ def mset_capable? # :nodoc:
328
304
  set_redis_capabilities unless defined? @mset_capable
329
305
  @mset_capable
330
306
  end
@@ -344,9 +320,12 @@ module ActiveSupport
344
320
  # Store provider interface:
345
321
  # Read an entry from the cache.
346
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)
347
327
  failsafe :read_entry do
348
- raw = options&.fetch(:raw, false)
349
- deserialize_entry(redis.with { |c| c.get(key) }, raw: raw)
328
+ redis.with { |c| c.get(key) }
350
329
  end
351
330
  end
352
331
 
@@ -383,9 +362,11 @@ module ActiveSupport
383
362
  # Write an entry to the cache.
384
363
  #
385
364
  # 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)
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
388
368
 
369
+ def write_serialized_entry(key, payload, raw: false, unless_exist: false, expires_in: nil, race_condition_ttl: nil, **options)
389
370
  # If race condition TTL is in use, ensure that cache entries
390
371
  # stick around a bit longer after they would have expired
391
372
  # so we can purposefully serve stale entries.
@@ -393,16 +374,14 @@ module ActiveSupport
393
374
  expires_in += 5.minutes
394
375
  end
395
376
 
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
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
401
382
 
402
- redis.with { |c| c.set key, serialized_entry, **modifiers }
403
- else
404
- redis.with { |c| c.set key, serialized_entry }
405
- end
383
+ failsafe :write_entry, returning: false do
384
+ redis.with { |c| c.set key, payload, **modifiers }
406
385
  end
407
386
  end
408
387
 
@@ -429,7 +408,10 @@ module ActiveSupport
429
408
  if entries.any?
430
409
  if mset_capable? && expires_in.nil?
431
410
  failsafe :write_multi_entries do
432
- 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
433
415
  end
434
416
  else
435
417
  super
@@ -444,7 +426,7 @@ module ActiveSupport
444
426
 
445
427
  def truncate_key(key)
446
428
  if key && key.bytesize > max_key_bytesize
447
- suffix = ":sha2:#{::Digest::SHA2.hexdigest(key)}"
429
+ suffix = ":hash:#{ActiveSupport::Digest.hexdigest(key)}"
448
430
  truncate_at = max_key_bytesize - suffix.bytesize
449
431
  "#{key.byteslice(0, truncate_at)}#{suffix}"
450
432
  else
@@ -452,42 +434,35 @@ module ActiveSupport
452
434
  end
453
435
  end
454
436
 
455
- def deserialize_entry(payload, raw:)
456
- if payload && raw
457
- Entry.new(payload, compress: false)
437
+ def deserialize_entry(payload, raw: false, **)
438
+ if raw && !payload.nil?
439
+ Entry.new(payload)
458
440
  else
459
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
- super(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,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)