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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +231 -515
- data/lib/active_support/actionable_error.rb +1 -1
- data/lib/active_support/array_inquirer.rb +0 -2
- data/lib/active_support/backtrace_cleaner.rb +2 -2
- data/lib/active_support/benchmarkable.rb +2 -2
- data/lib/active_support/cache/file_store.rb +15 -9
- data/lib/active_support/cache/mem_cache_store.rb +132 -37
- data/lib/active_support/cache/memory_store.rb +24 -16
- data/lib/active_support/cache/null_store.rb +10 -2
- data/lib/active_support/cache/redis_cache_store.rb +47 -72
- data/lib/active_support/cache/strategy/local_cache.rb +38 -61
- data/lib/active_support/cache.rb +193 -46
- data/lib/active_support/callbacks.rb +184 -85
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +5 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +8 -5
- data/lib/active_support/configuration_file.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +13 -12
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/subclasses.rb +25 -17
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +9 -9
- data/lib/active_support/core_ext/date/conversions.rb +14 -14
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date.rb +1 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +4 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +13 -13
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +1 -0
- data/lib/active_support/core_ext/digest/uuid.rb +39 -14
- data/lib/active_support/core_ext/enumerable.rb +101 -32
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +0 -1
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +1 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +19 -10
- data/lib/active_support/core_ext/module/delegation.rb +2 -8
- data/lib/active_support/core_ext/name_error.rb +2 -8
- data/lib/active_support/core_ext/numeric/conversions.rb +80 -77
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +11 -0
- data/lib/active_support/core_ext/object/json.rb +30 -25
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with_options.rb +20 -1
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +0 -25
- data/lib/active_support/core_ext/range/conversions.rb +8 -8
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -25
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/range.rb +1 -1
- data/lib/active_support/core_ext/securerandom.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +1 -1
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +62 -38
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
- data/lib/active_support/core_ext/time/calculations.rb +7 -8
- data/lib/active_support/core_ext/time/conversions.rb +13 -12
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +7 -22
- data/lib/active_support/core_ext/time.rb +1 -0
- data/lib/active_support/core_ext/uri.rb +3 -27
- data/lib/active_support/core_ext.rb +1 -0
- data/lib/active_support/current_attributes.rb +31 -14
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -788
- data/lib/active_support/deprecation/behaviors.rb +5 -2
- data/lib/active_support/deprecation/method_wrappers.rb +3 -3
- data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
- data/lib/active_support/deprecation.rb +2 -2
- data/lib/active_support/descendants_tracker.rb +174 -68
- data/lib/active_support/digest.rb +4 -4
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +9 -1
- data/lib/active_support/duration.rb +77 -48
- data/lib/active_support/encrypted_configuration.rb +13 -2
- data/lib/active_support/encrypted_file.rb +1 -1
- data/lib/active_support/environment_inquirer.rb +1 -1
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +3 -5
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +30 -11
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/fork_tracker.rb +19 -12
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +3 -1
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +1 -1
- data/lib/active_support/inflector/inflections.rb +23 -7
- data/lib/active_support/inflector/methods.rb +24 -48
- data/lib/active_support/inflector/transliterate.rb +1 -1
- data/lib/active_support/isolated_execution_state.rb +72 -0
- data/lib/active_support/json/encoding.rb +3 -3
- data/lib/active_support/key_generator.rb +22 -5
- data/lib/active_support/lazy_load_hooks.rb +14 -3
- data/lib/active_support/locale/en.yml +1 -1
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +15 -5
- data/lib/active_support/logger.rb +4 -5
- data/lib/active_support/logger_thread_safe_level.rb +4 -13
- data/lib/active_support/message_encryptor.rb +12 -6
- data/lib/active_support/message_verifier.rb +46 -14
- data/lib/active_support/messages/metadata.rb +2 -2
- data/lib/active_support/multibyte/chars.rb +10 -11
- data/lib/active_support/multibyte/unicode.rb +0 -12
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +91 -65
- data/lib/active_support/notifications/instrumenter.rb +32 -15
- data/lib/active_support/notifications.rb +17 -23
- data/lib/active_support/number_helper/number_converter.rb +1 -3
- data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
- data/lib/active_support/number_helper/rounding_helper.rb +1 -5
- data/lib/active_support/number_helper.rb +0 -2
- data/lib/active_support/option_merger.rb +8 -16
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +1 -1
- data/lib/active_support/parameter_filter.rb +5 -0
- data/lib/active_support/per_thread_registry.rb +5 -1
- data/lib/active_support/railtie.rb +69 -19
- data/lib/active_support/rescuable.rb +4 -4
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +2 -2
- data/lib/active_support/string_inquirer.rb +0 -2
- data/lib/active_support/subscriber.rb +7 -18
- data/lib/active_support/tagged_logging.rb +16 -1
- data/lib/active_support/test_case.rb +9 -21
- data/lib/active_support/testing/assertions.rb +35 -5
- data/lib/active_support/testing/deprecation.rb +52 -1
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +5 -5
- data/lib/active_support/testing/parallelization/server.rb +4 -0
- data/lib/active_support/testing/parallelization/worker.rb +3 -0
- data/lib/active_support/testing/parallelization.rb +4 -0
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/stream.rb +3 -5
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +13 -2
- data/lib/active_support/time_with_zone.rb +58 -17
- data/lib/active_support/values/time_zone.rb +33 -14
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +4 -4
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +5 -4
- data/lib/active_support.rb +16 -0
- metadata +23 -21
- data/lib/active_support/core_ext/marshal.rb +0 -26
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -120
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
|
-
# Actionable errors
|
4
|
+
# Actionable errors lets you define actions to resolve an error.
|
5
5
|
#
|
6
6
|
# To make an error actionable, include the <tt>ActiveSupport::ActionableError</tt>
|
7
7
|
# module and invoke the +action+ class macro to define the action. An action
|
@@ -21,10 +21,10 @@ module ActiveSupport
|
|
21
21
|
#
|
22
22
|
# To reconfigure an existing BacktraceCleaner (like the default one in Rails)
|
23
23
|
# and show as much data as possible, you can always call
|
24
|
-
#
|
24
|
+
# BacktraceCleaner#remove_silencers!, which will restore the
|
25
25
|
# backtrace to a pristine state. If you need to reconfigure an existing
|
26
26
|
# BacktraceCleaner so that it does not filter or modify the paths of any lines
|
27
|
-
# of the backtrace, you can call
|
27
|
+
# of the backtrace, you can call BacktraceCleaner#remove_filters!
|
28
28
|
# These two methods will give you a completely untouched backtrace.
|
29
29
|
#
|
30
30
|
# Inspired by the Quiet Backtrace gem by thoughtbot.
|
@@ -34,13 +34,13 @@ module ActiveSupport
|
|
34
34
|
# <% benchmark 'Process data files', level: :info, silence: true do %>
|
35
35
|
# <%= expensive_and_chatty_files_operation %>
|
36
36
|
# <% end %>
|
37
|
-
def benchmark(message = "Benchmarking", options = {})
|
37
|
+
def benchmark(message = "Benchmarking", options = {}, &block)
|
38
38
|
if logger
|
39
39
|
options.assert_valid_keys(:level, :silence)
|
40
40
|
options[:level] ||= :info
|
41
41
|
|
42
42
|
result = nil
|
43
|
-
ms = Benchmark.ms { result = options[:silence] ? logger.silence
|
43
|
+
ms = Benchmark.ms { result = options[:silence] ? logger.silence(&block) : yield }
|
44
44
|
logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
|
45
45
|
result
|
46
46
|
else
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/marshal"
|
4
3
|
require "active_support/core_ext/file/atomic"
|
5
4
|
require "active_support/core_ext/string/conversions"
|
6
5
|
require "uri/common"
|
@@ -12,7 +11,6 @@ module ActiveSupport
|
|
12
11
|
# FileStore implements the Strategy::LocalCache strategy which implements
|
13
12
|
# an in-memory cache inside of a block.
|
14
13
|
class FileStore < Store
|
15
|
-
prepend Strategy::LocalCache
|
16
14
|
attr_reader :cache_path
|
17
15
|
|
18
16
|
DIR_FORMATTER = "%03X"
|
@@ -73,19 +71,27 @@ module ActiveSupport
|
|
73
71
|
|
74
72
|
private
|
75
73
|
def read_entry(key, **options)
|
76
|
-
if
|
77
|
-
entry =
|
74
|
+
if payload = read_serialized_entry(key, **options)
|
75
|
+
entry = deserialize_entry(payload)
|
78
76
|
entry if entry.is_a?(Cache::Entry)
|
79
77
|
end
|
80
|
-
|
81
|
-
|
78
|
+
end
|
79
|
+
|
80
|
+
def read_serialized_entry(key, **)
|
81
|
+
File.binread(key) if File.exist?(key)
|
82
|
+
rescue => error
|
83
|
+
logger.error("FileStoreError (#{error}): #{error.message}") if logger
|
82
84
|
nil
|
83
85
|
end
|
84
86
|
|
85
87
|
def write_entry(key, entry, **options)
|
88
|
+
write_serialized_entry(key, serialize_entry(entry, **options), **options)
|
89
|
+
end
|
90
|
+
|
91
|
+
def write_serialized_entry(key, payload, **options)
|
86
92
|
return false if options[:unless_exist] && File.exist?(key)
|
87
93
|
ensure_cache_path(File.dirname(key))
|
88
|
-
File.atomic_write(key, cache_path) { |f| f.write(
|
94
|
+
File.atomic_write(key, cache_path) { |f| f.write(payload) }
|
89
95
|
true
|
90
96
|
end
|
91
97
|
|
@@ -95,9 +101,9 @@ module ActiveSupport
|
|
95
101
|
File.delete(key)
|
96
102
|
delete_empty_directories(File.dirname(key))
|
97
103
|
true
|
98
|
-
rescue
|
104
|
+
rescue
|
99
105
|
# Just in case the error was caused by another process deleting the file first.
|
100
|
-
raise
|
106
|
+
raise if File.exist?(key)
|
101
107
|
false
|
102
108
|
end
|
103
109
|
end
|
@@ -7,8 +7,8 @@ rescue LoadError => e
|
|
7
7
|
raise e
|
8
8
|
end
|
9
9
|
|
10
|
+
require "delegate"
|
10
11
|
require "active_support/core_ext/enumerable"
|
11
|
-
require "active_support/core_ext/marshal"
|
12
12
|
require "active_support/core_ext/array/extract_options"
|
13
13
|
|
14
14
|
module ActiveSupport
|
@@ -26,29 +26,52 @@ module ActiveSupport
|
|
26
26
|
# MemCacheStore implements the Strategy::LocalCache strategy which implements
|
27
27
|
# an in-memory cache inside of a block.
|
28
28
|
class MemCacheStore < Store
|
29
|
-
|
29
|
+
# Advertise cache versioning support.
|
30
|
+
def self.supports_cache_versioning?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
prepend Strategy::LocalCache
|
35
|
+
|
36
|
+
module DupLocalCache
|
37
|
+
class DupLocalStore < DelegateClass(Strategy::LocalCache::LocalStore)
|
38
|
+
def write_entry(_key, entry)
|
39
|
+
if entry.is_a?(Entry)
|
40
|
+
entry.dup_value!
|
41
|
+
end
|
42
|
+
super
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch_entry(key)
|
46
|
+
entry = super do
|
47
|
+
new_entry = yield
|
48
|
+
if entry.is_a?(Entry)
|
49
|
+
new_entry.dup_value!
|
50
|
+
end
|
51
|
+
new_entry
|
52
|
+
end
|
53
|
+
entry = entry.dup
|
54
|
+
|
55
|
+
if entry.is_a?(Entry)
|
56
|
+
entry.dup_value!
|
57
|
+
end
|
58
|
+
|
59
|
+
entry
|
60
|
+
end
|
61
|
+
end
|
30
62
|
|
31
|
-
# Provide support for raw values in the local cache strategy.
|
32
|
-
module LocalCacheWithRaw # :nodoc:
|
33
63
|
private
|
34
|
-
def
|
35
|
-
if
|
36
|
-
|
37
|
-
|
38
|
-
|
64
|
+
def local_cache
|
65
|
+
if ActiveSupport::Cache.format_version == 6.1
|
66
|
+
if local_cache = super
|
67
|
+
DupLocalStore.new(local_cache)
|
68
|
+
end
|
39
69
|
else
|
40
70
|
super
|
41
71
|
end
|
42
72
|
end
|
43
73
|
end
|
44
|
-
|
45
|
-
# Advertise cache versioning support.
|
46
|
-
def self.supports_cache_versioning?
|
47
|
-
true
|
48
|
-
end
|
49
|
-
|
50
|
-
prepend Strategy::LocalCache
|
51
|
-
prepend LocalCacheWithRaw
|
74
|
+
prepend DupLocalCache
|
52
75
|
|
53
76
|
ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
|
54
77
|
|
@@ -81,11 +104,14 @@ module ActiveSupport
|
|
81
104
|
#
|
82
105
|
# ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
|
83
106
|
#
|
84
|
-
# If no addresses are provided, but ENV['MEMCACHE_SERVERS'] is defined, it will be used instead. Otherwise,
|
107
|
+
# If no addresses are provided, but <tt>ENV['MEMCACHE_SERVERS']</tt> is defined, it will be used instead. Otherwise,
|
85
108
|
# MemCacheStore will connect to localhost:11211 (the default memcached port).
|
86
109
|
def initialize(*addresses)
|
87
110
|
addresses = addresses.flatten
|
88
111
|
options = addresses.extract_options!
|
112
|
+
if options.key?(:cache_nils)
|
113
|
+
options[:skip_nil] = !options.delete(:cache_nils)
|
114
|
+
end
|
89
115
|
super(options)
|
90
116
|
|
91
117
|
unless [String, Dalli::Client, NilClass].include?(addresses.first.class)
|
@@ -95,14 +121,16 @@ module ActiveSupport
|
|
95
121
|
@data = addresses.first
|
96
122
|
else
|
97
123
|
mem_cache_options = options.dup
|
98
|
-
|
124
|
+
# The value "compress: false" prevents duplicate compression within Dalli.
|
125
|
+
mem_cache_options[:compress] = false
|
126
|
+
(UNIVERSAL_OPTIONS - %i(compress)).each { |name| mem_cache_options.delete(name) }
|
99
127
|
@data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
|
100
128
|
end
|
101
129
|
end
|
102
130
|
|
103
131
|
# Increment a cached value. This method uses the memcached incr atomic
|
104
|
-
# operator and can only be used on values written with the
|
105
|
-
# Calling it on a value not stored with
|
132
|
+
# operator and can only be used on values written with the +:raw+ option.
|
133
|
+
# Calling it on a value not stored with +:raw+ will initialize that value
|
106
134
|
# to zero.
|
107
135
|
def increment(name, amount = 1, options = nil)
|
108
136
|
options = merged_options(options)
|
@@ -114,8 +142,8 @@ module ActiveSupport
|
|
114
142
|
end
|
115
143
|
|
116
144
|
# Decrement a cached value. This method uses the memcached decr atomic
|
117
|
-
# operator and can only be used on values written with the
|
118
|
-
# Calling it on a value not stored with
|
145
|
+
# operator and can only be used on values written with the +:raw+ option.
|
146
|
+
# Calling it on a value not stored with +:raw+ will initialize that value
|
119
147
|
# to zero.
|
120
148
|
def decrement(name, amount = 1, options = nil)
|
121
149
|
options = merged_options(options)
|
@@ -138,23 +166,81 @@ module ActiveSupport
|
|
138
166
|
end
|
139
167
|
|
140
168
|
private
|
169
|
+
module Coders # :nodoc:
|
170
|
+
class << self
|
171
|
+
def [](version)
|
172
|
+
case version
|
173
|
+
when 6.1
|
174
|
+
Rails61Coder
|
175
|
+
when 7.0
|
176
|
+
Rails70Coder
|
177
|
+
else
|
178
|
+
raise ArgumentError, "Unknown ActiveSupport::Cache.format_version #{Cache.format_version.inspect}"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
module Loader
|
184
|
+
def load(payload)
|
185
|
+
if payload.is_a?(Entry)
|
186
|
+
payload
|
187
|
+
else
|
188
|
+
Cache::Coders::Loader.load(payload)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
module Rails61Coder
|
194
|
+
include Loader
|
195
|
+
extend self
|
196
|
+
|
197
|
+
def dump(entry)
|
198
|
+
entry
|
199
|
+
end
|
200
|
+
|
201
|
+
def dump_compressed(entry, threshold)
|
202
|
+
entry.compressed(threshold)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
module Rails70Coder
|
207
|
+
include Cache::Coders::Rails70Coder
|
208
|
+
include Loader
|
209
|
+
extend self
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def default_coder
|
214
|
+
Coders[Cache.format_version]
|
215
|
+
end
|
216
|
+
|
141
217
|
# Read an entry from the cache.
|
142
218
|
def read_entry(key, **options)
|
143
|
-
|
219
|
+
deserialize_entry(read_serialized_entry(key, **options), **options)
|
220
|
+
end
|
221
|
+
|
222
|
+
def read_serialized_entry(key, **options)
|
223
|
+
rescue_error_with(nil) do
|
224
|
+
@data.with { |c| c.get(key, options) }
|
225
|
+
end
|
144
226
|
end
|
145
227
|
|
146
228
|
# Write an entry to the cache.
|
147
229
|
def write_entry(key, entry, **options)
|
230
|
+
write_serialized_entry(key, serialize_entry(entry, **options), **options)
|
231
|
+
end
|
232
|
+
|
233
|
+
def write_serialized_entry(key, payload, **options)
|
148
234
|
method = options[:unless_exist] ? :add : :set
|
149
|
-
value = options[:raw] ? entry.value.to_s : serialize_entry(entry)
|
150
235
|
expires_in = options[:expires_in].to_i
|
151
236
|
if options[:race_condition_ttl] && expires_in > 0 && !options[:raw]
|
152
237
|
# Set the memcache expire a few minutes in the future to support race condition ttls on read
|
153
238
|
expires_in += 5.minutes
|
154
239
|
end
|
155
240
|
rescue_error_with false do
|
156
|
-
#
|
157
|
-
|
241
|
+
# Don't pass compress option to Dalli since we are already dealing with compression.
|
242
|
+
options.delete(:compress)
|
243
|
+
@data.with { |c| c.send(method, key, payload, expires_in, **options) }
|
158
244
|
end
|
159
245
|
end
|
160
246
|
|
@@ -166,7 +252,7 @@ module ActiveSupport
|
|
166
252
|
values = {}
|
167
253
|
|
168
254
|
raw_values.each do |key, value|
|
169
|
-
entry = deserialize_entry(value)
|
255
|
+
entry = deserialize_entry(value, raw: options[:raw])
|
170
256
|
|
171
257
|
unless entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
|
172
258
|
values[keys_to_names[key]] = entry.value
|
@@ -181,31 +267,40 @@ module ActiveSupport
|
|
181
267
|
rescue_error_with(false) { @data.with { |c| c.delete(key) } }
|
182
268
|
end
|
183
269
|
|
270
|
+
def serialize_entry(entry, raw: false, **options)
|
271
|
+
if raw
|
272
|
+
entry.value.to_s
|
273
|
+
else
|
274
|
+
super(entry, raw: raw, **options)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
184
278
|
# Memcache keys are binaries. So we need to force their encoding to binary
|
185
279
|
# before applying the regular expression to ensure we are escaping all
|
186
280
|
# characters properly.
|
187
281
|
def normalize_key(key, options)
|
188
282
|
key = super
|
189
|
-
|
190
283
|
if key
|
191
284
|
key = key.dup.force_encoding(Encoding::ASCII_8BIT)
|
192
285
|
key = key.gsub(ESCAPE_KEY_CHARS) { |match| "%#{match.getbyte(0).to_s(16).upcase}" }
|
193
|
-
key = "#{key[0,
|
286
|
+
key = "#{key[0, 212]}:hash:#{ActiveSupport::Digest.hexdigest(key)}" if key.size > 250
|
194
287
|
end
|
195
|
-
|
196
288
|
key
|
197
289
|
end
|
198
290
|
|
199
|
-
def deserialize_entry(payload)
|
200
|
-
|
201
|
-
|
202
|
-
|
291
|
+
def deserialize_entry(payload, raw: false, **)
|
292
|
+
if payload && raw
|
293
|
+
Entry.new(payload)
|
294
|
+
else
|
295
|
+
super(payload)
|
296
|
+
end
|
203
297
|
end
|
204
298
|
|
205
299
|
def rescue_error_with(fallback)
|
206
300
|
yield
|
207
|
-
rescue Dalli::DalliError =>
|
208
|
-
|
301
|
+
rescue Dalli::DalliError => error
|
302
|
+
ActiveSupport.error_reporter&.report(error, handled: true, severity: :warning)
|
303
|
+
logger.error("DalliError (#{error}): #{error.message}") if logger
|
209
304
|
fallback
|
210
305
|
end
|
211
306
|
end
|
@@ -11,7 +11,7 @@ module ActiveSupport
|
|
11
11
|
# to share cache data with each other and this may not be the most
|
12
12
|
# appropriate cache in that scenario.
|
13
13
|
#
|
14
|
-
# This cache has a bounded size specified by the
|
14
|
+
# This cache has a bounded size specified by the +:size+ options to the
|
15
15
|
# initializer (default is 32Mb). When the cache exceeds the allotted size,
|
16
16
|
# a cleanup will occur which tries to prune the cache down to three quarters
|
17
17
|
# of the maximum size by removing the least recently used entries.
|
@@ -25,21 +25,25 @@ module ActiveSupport
|
|
25
25
|
# MemoryStore is thread-safe.
|
26
26
|
class MemoryStore < Store
|
27
27
|
module DupCoder # :nodoc:
|
28
|
-
|
29
|
-
def load(entry)
|
30
|
-
entry = entry.dup
|
31
|
-
entry.dup_value!
|
32
|
-
entry
|
33
|
-
end
|
28
|
+
extend self
|
34
29
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
30
|
+
def dump(entry)
|
31
|
+
entry.dup_value! unless entry.compressed?
|
32
|
+
entry
|
33
|
+
end
|
34
|
+
|
35
|
+
def dump_compressed(entry, threshold)
|
36
|
+
entry = entry.compressed(threshold)
|
37
|
+
entry.dup_value! unless entry.compressed?
|
38
|
+
entry
|
39
39
|
end
|
40
|
-
end
|
41
40
|
|
42
|
-
|
41
|
+
def load(entry)
|
42
|
+
entry = entry.dup
|
43
|
+
entry.dup_value!
|
44
|
+
entry
|
45
|
+
end
|
46
|
+
end
|
43
47
|
|
44
48
|
def initialize(options = nil)
|
45
49
|
options ||= {}
|
@@ -85,13 +89,13 @@ module ActiveSupport
|
|
85
89
|
return if pruning?
|
86
90
|
@pruning = true
|
87
91
|
begin
|
88
|
-
start_time =
|
92
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
89
93
|
cleanup
|
90
94
|
instrument(:prune, target_size, from: @cache_size) do
|
91
95
|
keys = synchronize { @data.keys }
|
92
96
|
keys.each do |key|
|
93
97
|
delete_entry(key, **options)
|
94
|
-
return if @cache_size <= target_size || (max_time &&
|
98
|
+
return if @cache_size <= target_size || (max_time && Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time > max_time)
|
95
99
|
end
|
96
100
|
end
|
97
101
|
ensure
|
@@ -139,6 +143,10 @@ module ActiveSupport
|
|
139
143
|
private
|
140
144
|
PER_ENTRY_OVERHEAD = 240
|
141
145
|
|
146
|
+
def default_coder
|
147
|
+
DupCoder
|
148
|
+
end
|
149
|
+
|
142
150
|
def cached_size(key, payload)
|
143
151
|
key.to_s.bytesize + payload.bytesize + PER_ENTRY_OVERHEAD
|
144
152
|
end
|
@@ -156,7 +164,7 @@ module ActiveSupport
|
|
156
164
|
end
|
157
165
|
|
158
166
|
def write_entry(key, entry, **options)
|
159
|
-
payload = serialize_entry(entry)
|
167
|
+
payload = serialize_entry(entry, **options)
|
160
168
|
synchronize do
|
161
169
|
return false if options[:unless_exist] && @data.key?(key)
|
162
170
|
|
@@ -33,10 +33,18 @@ module ActiveSupport
|
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
36
|
-
def read_entry(key, **
|
36
|
+
def read_entry(key, **s)
|
37
|
+
deserialize_entry(read_serialized_entry(key))
|
37
38
|
end
|
38
39
|
|
39
|
-
def
|
40
|
+
def read_serialized_entry(_key, **)
|
41
|
+
end
|
42
|
+
|
43
|
+
def write_entry(key, entry, **)
|
44
|
+
write_serialized_entry(key, serialize_entry(entry))
|
45
|
+
end
|
46
|
+
|
47
|
+
def write_serialized_entry(_key, _payload, **)
|
40
48
|
true
|
41
49
|
end
|
42
50
|
|