activesupport 7.0.8.7 → 7.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +722 -314
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +2 -0
- data/lib/active_support/backtrace_cleaner.rb +25 -5
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +128 -0
- data/lib/active_support/cache/file_store.rb +36 -9
- data/lib/active_support/cache/mem_cache_store.rb +84 -68
- data/lib/active_support/cache/memory_store.rb +76 -24
- data/lib/active_support/cache/null_store.rb +6 -0
- data/lib/active_support/cache/redis_cache_store.rb +126 -131
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +20 -8
- data/lib/active_support/cache.rb +304 -246
- data/lib/active_support/callbacks.rb +38 -18
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +10 -0
- data/lib/active_support/core_ext/array/conversions.rb +2 -1
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/class/subclasses.rb +13 -10
- data/lib/active_support/core_ext/date/conversions.rb +1 -0
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +1 -10
- data/lib/active_support/core_ext/enumerable.rb +3 -75
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
- data/lib/active_support/core_ext/module/delegation.rb +40 -11
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/duplicable.rb +15 -24
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +10 -2
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +3 -3
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +28 -7
- data/lib/active_support/core_ext/range/{overlaps.rb → overlap.rb} +5 -3
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +24 -12
- data/lib/active_support/core_ext/string/filters.rb +20 -14
- data/lib/active_support/core_ext/string/inflections.rb +16 -5
- data/lib/active_support/core_ext/string/output_safety.rb +38 -174
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +18 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -2
- data/lib/active_support/core_ext/time/zones.rb +4 -4
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/current_attributes.rb +15 -6
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/deprecation/behaviors.rb +53 -32
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +3 -5
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
- data/lib/active_support/deprecation/reporting.rb +35 -21
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +104 -132
- data/lib/active_support/duration/iso8601_serializer.rb +0 -2
- data/lib/active_support/duration.rb +2 -1
- data/lib/active_support/encrypted_configuration.rb +30 -9
- data/lib/active_support/encrypted_file.rb +8 -3
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +121 -35
- data/lib/active_support/execution_wrapper.rb +4 -4
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +10 -2
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +35 -17
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +22 -10
- data/lib/active_support/inflector/transliterate.rb +3 -1
- data/lib/active_support/isolated_execution_state.rb +26 -22
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +25 -43
- data/lib/active_support/key_generator.rb +9 -1
- data/lib/active_support/lazy_load_hooks.rb +6 -4
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +78 -33
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_thread_safe_level.rb +9 -21
- data/lib/active_support/message_encryptor.rb +197 -53
- data/lib/active_support/message_encryptors.rb +140 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +212 -93
- data/lib/active_support/message_verifiers.rb +134 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +111 -45
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +239 -81
- data/lib/active_support/notifications/instrumenter.rb +71 -14
- data/lib/active_support/notifications.rb +1 -1
- data/lib/active_support/number_helper/number_converter.rb +2 -2
- 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 -0
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +14 -0
- data/lib/active_support/parameter_filter.rb +84 -69
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +33 -21
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +2 -0
- data/lib/active_support/secure_compare_rotator.rb +16 -9
- data/lib/active_support/string_inquirer.rb +3 -1
- data/lib/active_support/subscriber.rb +9 -27
- data/lib/active_support/syntax_error_proxy.rb +49 -0
- data/lib/active_support/tagged_logging.rb +60 -24
- data/lib/active_support/test_case.rb +153 -6
- data/lib/active_support/testing/assertions.rb +25 -9
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +25 -25
- data/lib/active_support/testing/error_reporter_assertions.rb +108 -0
- data/lib/active_support/testing/isolation.rb +1 -1
- data/lib/active_support/testing/method_call_assertions.rb +21 -8
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +38 -0
- data/lib/active_support/testing/time_helpers.rb +32 -14
- data/lib/active_support/time_with_zone.rb +4 -14
- data/lib/active_support/values/time_zone.rb +9 -7
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- 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 +2 -2
- data/lib/active_support.rb +13 -3
- metadata +106 -21
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/per_thread_registry.rb +0 -65
@@ -3,16 +3,20 @@
|
|
3
3
|
begin
|
4
4
|
require "dalli"
|
5
5
|
rescue LoadError => e
|
6
|
-
|
6
|
+
warn "You don't have dalli installed in your application. Please add it to your Gemfile and run bundle install"
|
7
7
|
raise e
|
8
8
|
end
|
9
9
|
|
10
|
+
require "connection_pool"
|
10
11
|
require "delegate"
|
11
12
|
require "active_support/core_ext/enumerable"
|
12
13
|
require "active_support/core_ext/array/extract_options"
|
14
|
+
require "active_support/core_ext/numeric/time"
|
13
15
|
|
14
16
|
module ActiveSupport
|
15
17
|
module Cache
|
18
|
+
# = Memcached \Cache \Store
|
19
|
+
#
|
16
20
|
# A cache store implementation which stores data in Memcached:
|
17
21
|
# https://memcached.org
|
18
22
|
#
|
@@ -26,6 +30,10 @@ module ActiveSupport
|
|
26
30
|
# MemCacheStore implements the Strategy::LocalCache strategy which implements
|
27
31
|
# an in-memory cache inside of a block.
|
28
32
|
class MemCacheStore < Store
|
33
|
+
# These options represent behavior overridden by this implementation and should
|
34
|
+
# not be allowed to get down to the Dalli client
|
35
|
+
OVERRIDDEN_OPTIONS = UNIVERSAL_OPTIONS
|
36
|
+
|
29
37
|
# Advertise cache versioning support.
|
30
38
|
def self.supports_cache_versioning?
|
31
39
|
true
|
@@ -73,6 +81,7 @@ module ActiveSupport
|
|
73
81
|
end
|
74
82
|
prepend DupLocalCache
|
75
83
|
|
84
|
+
KEY_MAX_SIZE = 250
|
76
85
|
ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
|
77
86
|
|
78
87
|
# Creates a new Dalli::Client instance with specified addresses and options.
|
@@ -90,11 +99,10 @@ module ActiveSupport
|
|
90
99
|
addresses = nil if addresses.compact.empty?
|
91
100
|
pool_options = retrieve_pool_options(options)
|
92
101
|
|
93
|
-
if pool_options
|
94
|
-
Dalli::Client.new(addresses, options)
|
95
|
-
else
|
96
|
-
ensure_connection_pool_added!
|
102
|
+
if pool_options
|
97
103
|
ConnectionPool.new(pool_options) { Dalli::Client.new(addresses, options.merge(threadsafe: false)) }
|
104
|
+
else
|
105
|
+
Dalli::Client.new(addresses, options)
|
98
106
|
end
|
99
107
|
end
|
100
108
|
|
@@ -106,6 +114,7 @@ module ActiveSupport
|
|
106
114
|
#
|
107
115
|
# If no addresses are provided, but <tt>ENV['MEMCACHE_SERVERS']</tt> is defined, it will be used instead. Otherwise,
|
108
116
|
# MemCacheStore will connect to localhost:11211 (the default memcached port).
|
117
|
+
# Passing a +Dalli::Client+ instance is deprecated and will be removed. Please pass an address instead.
|
109
118
|
def initialize(*addresses)
|
110
119
|
addresses = addresses.flatten
|
111
120
|
options = addresses.extract_options!
|
@@ -115,19 +124,28 @@ module ActiveSupport
|
|
115
124
|
super(options)
|
116
125
|
|
117
126
|
unless [String, Dalli::Client, NilClass].include?(addresses.first.class)
|
118
|
-
raise ArgumentError, "First argument must be an empty array,
|
127
|
+
raise ArgumentError, "First argument must be an empty array, address, or array of addresses."
|
119
128
|
end
|
120
129
|
if addresses.first.is_a?(Dalli::Client)
|
130
|
+
ActiveSupport.deprecator.warn(<<~MSG)
|
131
|
+
Initializing MemCacheStore with a Dalli::Client is deprecated and will be removed in Rails 7.2.
|
132
|
+
Use memcached server addresses instead.
|
133
|
+
MSG
|
121
134
|
@data = addresses.first
|
122
135
|
else
|
123
|
-
mem_cache_options = options.dup
|
136
|
+
@mem_cache_options = options.dup
|
124
137
|
# The value "compress: false" prevents duplicate compression within Dalli.
|
125
|
-
mem_cache_options[:compress] = false
|
126
|
-
(
|
127
|
-
@data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
|
138
|
+
@mem_cache_options[:compress] = false
|
139
|
+
(OVERRIDDEN_OPTIONS - %i(compress)).each { |name| @mem_cache_options.delete(name) }
|
140
|
+
@data = self.class.build_mem_cache(*(addresses + [@mem_cache_options]))
|
128
141
|
end
|
129
142
|
end
|
130
143
|
|
144
|
+
def inspect
|
145
|
+
instance = @data || @mem_cache_options
|
146
|
+
"#<#{self.class} options=#{options.inspect} mem_cache=#{instance.inspect}>"
|
147
|
+
end
|
148
|
+
|
131
149
|
##
|
132
150
|
# :method: write
|
133
151
|
# :call-seq: write(name, value, options = nil)
|
@@ -144,28 +162,50 @@ module ActiveSupport
|
|
144
162
|
# * <tt>unless_exist: true</tt> - Prevents overwriting an existing cache
|
145
163
|
# entry.
|
146
164
|
|
147
|
-
# Increment a cached value
|
148
|
-
#
|
149
|
-
#
|
150
|
-
# to
|
165
|
+
# Increment a cached integer value using the memcached incr atomic operator.
|
166
|
+
# Returns the updated value.
|
167
|
+
#
|
168
|
+
# If the key is unset or has expired, it will be set to +amount+:
|
169
|
+
#
|
170
|
+
# cache.increment("foo") # => 1
|
171
|
+
# cache.increment("bar", 100) # => 100
|
172
|
+
#
|
173
|
+
# To set a specific value, call #write passing <tt>raw: true</tt>:
|
174
|
+
#
|
175
|
+
# cache.write("baz", 5, raw: true)
|
176
|
+
# cache.increment("baz") # => 6
|
177
|
+
#
|
178
|
+
# Incrementing a non-numeric value, or a value written without
|
179
|
+
# <tt>raw: true</tt>, will fail and return +nil+.
|
151
180
|
def increment(name, amount = 1, options = nil)
|
152
181
|
options = merged_options(options)
|
153
182
|
instrument(:increment, name, amount: amount) do
|
154
183
|
rescue_error_with nil do
|
155
|
-
@data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in]) }
|
184
|
+
@data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in], amount) }
|
156
185
|
end
|
157
186
|
end
|
158
187
|
end
|
159
188
|
|
160
|
-
# Decrement a cached value
|
161
|
-
#
|
162
|
-
#
|
163
|
-
# to
|
189
|
+
# Decrement a cached integer value using the memcached decr atomic operator.
|
190
|
+
# Returns the updated value.
|
191
|
+
#
|
192
|
+
# If the key is unset or has expired, it will be set to 0. Memcached
|
193
|
+
# does not support negative counters.
|
194
|
+
#
|
195
|
+
# cache.decrement("foo") # => 0
|
196
|
+
#
|
197
|
+
# To set a specific value, call #write passing <tt>raw: true</tt>:
|
198
|
+
#
|
199
|
+
# cache.write("baz", 5, raw: true)
|
200
|
+
# cache.decrement("baz") # => 4
|
201
|
+
#
|
202
|
+
# Decrementing a non-numeric value, or a value written without
|
203
|
+
# <tt>raw: true</tt>, will fail and return +nil+.
|
164
204
|
def decrement(name, amount = 1, options = nil)
|
165
205
|
options = merged_options(options)
|
166
206
|
instrument(:decrement, name, amount: amount) do
|
167
207
|
rescue_error_with nil do
|
168
|
-
@data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in]) }
|
208
|
+
@data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in], 0) }
|
169
209
|
end
|
170
210
|
end
|
171
211
|
end
|
@@ -182,54 +222,20 @@ module ActiveSupport
|
|
182
222
|
end
|
183
223
|
|
184
224
|
private
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
module Loader
|
200
|
-
def load(payload)
|
201
|
-
if payload.is_a?(Entry)
|
202
|
-
payload
|
203
|
-
else
|
204
|
-
Cache::Coders::Loader.load(payload)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
module Rails61Coder
|
210
|
-
include Loader
|
211
|
-
extend self
|
212
|
-
|
213
|
-
def dump(entry)
|
214
|
-
entry
|
215
|
-
end
|
216
|
-
|
217
|
-
def dump_compressed(entry, threshold)
|
218
|
-
entry.compressed(threshold)
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
module Rails70Coder
|
223
|
-
include Cache::Coders::Rails70Coder
|
224
|
-
include Loader
|
225
|
-
extend self
|
225
|
+
def default_serializer
|
226
|
+
if Cache.format_version == 6.1
|
227
|
+
ActiveSupport.deprecator.warn <<~EOM
|
228
|
+
Support for `config.active_support.cache_format_version = 6.1` has been deprecated and will be removed in Rails 7.2.
|
229
|
+
|
230
|
+
Check the Rails upgrade guide at https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#new-activesupport-cache-serialization-format
|
231
|
+
for more information on how to upgrade.
|
232
|
+
EOM
|
233
|
+
Cache::SerializerWithFallback[:passthrough]
|
234
|
+
else
|
235
|
+
super
|
226
236
|
end
|
227
237
|
end
|
228
238
|
|
229
|
-
def default_coder
|
230
|
-
Coders[Cache.format_version]
|
231
|
-
end
|
232
|
-
|
233
239
|
# Read an entry from the cache.
|
234
240
|
def read_entry(key, **options)
|
235
241
|
deserialize_entry(read_serialized_entry(key, **options), **options)
|
@@ -270,7 +276,7 @@ module ActiveSupport
|
|
270
276
|
raw_values.each do |key, value|
|
271
277
|
entry = deserialize_entry(value, raw: options[:raw])
|
272
278
|
|
273
|
-
unless entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
|
279
|
+
unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
|
274
280
|
values[keys_to_names[key]] = entry.value
|
275
281
|
end
|
276
282
|
end
|
@@ -299,7 +305,13 @@ module ActiveSupport
|
|
299
305
|
if key
|
300
306
|
key = key.dup.force_encoding(Encoding::ASCII_8BIT)
|
301
307
|
key = key.gsub(ESCAPE_KEY_CHARS) { |match| "%#{match.getbyte(0).to_s(16).upcase}" }
|
302
|
-
|
308
|
+
|
309
|
+
if key.size > KEY_MAX_SIZE
|
310
|
+
key_separator = ":hash:"
|
311
|
+
key_hash = ActiveSupport::Digest.hexdigest(key)
|
312
|
+
key_trim_size = KEY_MAX_SIZE - key_separator.size - key_hash.size
|
313
|
+
key = "#{key[0, key_trim_size]}#{key_separator}#{key_hash}"
|
314
|
+
end
|
303
315
|
end
|
304
316
|
key
|
305
317
|
end
|
@@ -315,8 +327,12 @@ module ActiveSupport
|
|
315
327
|
def rescue_error_with(fallback)
|
316
328
|
yield
|
317
329
|
rescue Dalli::DalliError => error
|
318
|
-
ActiveSupport.error_reporter&.report(error, handled: true, severity: :warning)
|
319
330
|
logger.error("DalliError (#{error}): #{error.message}") if logger
|
331
|
+
ActiveSupport.error_reporter&.report(
|
332
|
+
error,
|
333
|
+
severity: :warning,
|
334
|
+
source: "mem_cache_store.active_support",
|
335
|
+
)
|
320
336
|
fallback
|
321
337
|
end
|
322
338
|
end
|
@@ -4,10 +4,12 @@ require "monitor"
|
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
module Cache
|
7
|
+
# = Memory \Cache \Store
|
8
|
+
#
|
7
9
|
# A cache store implementation which stores everything into memory in the
|
8
|
-
# same process. If you're running multiple Ruby on Rails server processes
|
10
|
+
# same process. If you're running multiple Ruby on \Rails server processes
|
9
11
|
# (which is the case if you're using Phusion Passenger or puma clustered mode),
|
10
|
-
# then this means that Rails server process instances won't be able
|
12
|
+
# then this means that \Rails server process instances won't be able
|
11
13
|
# to share cache data with each other and this may not be the most
|
12
14
|
# appropriate cache in that scenario.
|
13
15
|
#
|
@@ -28,25 +30,49 @@ module ActiveSupport
|
|
28
30
|
extend self
|
29
31
|
|
30
32
|
def dump(entry)
|
31
|
-
entry.
|
32
|
-
|
33
|
+
if entry.value && entry.value != true && !entry.value.is_a?(Numeric)
|
34
|
+
Cache::Entry.new(dump_value(entry.value), expires_at: entry.expires_at, version: entry.version)
|
35
|
+
else
|
36
|
+
entry
|
37
|
+
end
|
33
38
|
end
|
34
39
|
|
35
40
|
def dump_compressed(entry, threshold)
|
36
|
-
|
37
|
-
|
38
|
-
entry
|
41
|
+
compressed_entry = entry.compressed(threshold)
|
42
|
+
compressed_entry.compressed? ? compressed_entry : dump(entry)
|
39
43
|
end
|
40
44
|
|
41
45
|
def load(entry)
|
42
|
-
entry
|
43
|
-
|
44
|
-
|
46
|
+
if !entry.compressed? && entry.value.is_a?(String)
|
47
|
+
Cache::Entry.new(load_value(entry.value), expires_at: entry.expires_at, version: entry.version)
|
48
|
+
else
|
49
|
+
entry
|
50
|
+
end
|
45
51
|
end
|
52
|
+
|
53
|
+
private
|
54
|
+
MARSHAL_SIGNATURE = "\x04\x08".b.freeze
|
55
|
+
|
56
|
+
def dump_value(value)
|
57
|
+
if value.is_a?(String) && !value.start_with?(MARSHAL_SIGNATURE)
|
58
|
+
value.dup
|
59
|
+
else
|
60
|
+
Marshal.dump(value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def load_value(string)
|
65
|
+
if string.start_with?(MARSHAL_SIGNATURE)
|
66
|
+
Marshal.load(string)
|
67
|
+
else
|
68
|
+
string.dup
|
69
|
+
end
|
70
|
+
end
|
46
71
|
end
|
47
72
|
|
48
73
|
def initialize(options = nil)
|
49
74
|
options ||= {}
|
75
|
+
options[:coder] = DupCoder unless options.key?(:coder) || options.key?(:serializer)
|
50
76
|
# Disable compression by default.
|
51
77
|
options[:compress] ||= false
|
52
78
|
super(options)
|
@@ -74,7 +100,7 @@ module ActiveSupport
|
|
74
100
|
# Preemptively iterates through all stored keys and removes the ones which have expired.
|
75
101
|
def cleanup(options = nil)
|
76
102
|
options = merged_options(options)
|
77
|
-
|
103
|
+
_instrument(:cleanup, size: @data.size) do
|
78
104
|
keys = synchronize { @data.keys }
|
79
105
|
keys.each do |key|
|
80
106
|
entry = @data[key]
|
@@ -108,12 +134,33 @@ module ActiveSupport
|
|
108
134
|
@pruning
|
109
135
|
end
|
110
136
|
|
111
|
-
# Increment
|
137
|
+
# Increment a cached integer value. Returns the updated value.
|
138
|
+
#
|
139
|
+
# If the key is unset, it will be set to +amount+:
|
140
|
+
#
|
141
|
+
# cache.increment("foo") # => 1
|
142
|
+
# cache.increment("bar", 100) # => 100
|
143
|
+
#
|
144
|
+
# To set a specific value, call #write:
|
145
|
+
#
|
146
|
+
# cache.write("baz", 5)
|
147
|
+
# cache.increment("baz") # => 6
|
148
|
+
#
|
112
149
|
def increment(name, amount = 1, options = nil)
|
113
150
|
modify_value(name, amount, options)
|
114
151
|
end
|
115
152
|
|
116
|
-
# Decrement
|
153
|
+
# Decrement a cached integer value. Returns the updated value.
|
154
|
+
#
|
155
|
+
# If the key is unset or has expired, it will be set to +-amount+.
|
156
|
+
#
|
157
|
+
# cache.decrement("foo") # => -1
|
158
|
+
#
|
159
|
+
# To set a specific value, call #write:
|
160
|
+
#
|
161
|
+
# cache.write("baz", 5)
|
162
|
+
# cache.decrement("baz") # => 4
|
163
|
+
#
|
117
164
|
def decrement(name, amount = 1, options = nil)
|
118
165
|
modify_value(name, -amount, options)
|
119
166
|
end
|
@@ -143,10 +190,6 @@ module ActiveSupport
|
|
143
190
|
private
|
144
191
|
PER_ENTRY_OVERHEAD = 240
|
145
192
|
|
146
|
-
def default_coder
|
147
|
-
DupCoder
|
148
|
-
end
|
149
|
-
|
150
193
|
def cached_size(key, payload)
|
151
194
|
key.to_s.bytesize + payload.bytesize + PER_ENTRY_OVERHEAD
|
152
195
|
end
|
@@ -166,7 +209,7 @@ module ActiveSupport
|
|
166
209
|
def write_entry(key, entry, **options)
|
167
210
|
payload = serialize_entry(entry, **options)
|
168
211
|
synchronize do
|
169
|
-
return false if options[:unless_exist] &&
|
212
|
+
return false if options[:unless_exist] && exist?(key)
|
170
213
|
|
171
214
|
old_payload = @data[key]
|
172
215
|
if old_payload
|
@@ -188,14 +231,23 @@ module ActiveSupport
|
|
188
231
|
end
|
189
232
|
end
|
190
233
|
|
234
|
+
# Modifies the amount of an integer value that is stored in the cache.
|
235
|
+
# If the key is not found it is created and set to +amount+.
|
191
236
|
def modify_value(name, amount, options)
|
192
237
|
options = merged_options(options)
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
238
|
+
key = normalize_key(name, options)
|
239
|
+
version = normalize_version(name, options)
|
240
|
+
|
241
|
+
entry = read_entry(key, **options)
|
242
|
+
|
243
|
+
if !entry || entry.expired? || entry.mismatched?(version)
|
244
|
+
write(name, Integer(amount), options)
|
245
|
+
amount
|
246
|
+
else
|
247
|
+
num = entry.value.to_i + amount
|
248
|
+
entry = Entry.new(num, expires_at: entry.expires_at, version: entry.version)
|
249
|
+
write_entry(key, entry)
|
250
|
+
num
|
199
251
|
end
|
200
252
|
end
|
201
253
|
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
4
|
module Cache
|
5
|
+
# = Null \Cache \Store
|
6
|
+
#
|
5
7
|
# A cache store implementation which doesn't actually store anything. Useful in
|
6
8
|
# development and test environments where you don't want caching turned on but
|
7
9
|
# need to go through the caching interface.
|
@@ -32,6 +34,10 @@ module ActiveSupport
|
|
32
34
|
def delete_matched(matcher, options = nil)
|
33
35
|
end
|
34
36
|
|
37
|
+
def inspect # :nodoc:
|
38
|
+
"#<#{self.class.name} options=#{@options.inspect}>"
|
39
|
+
end
|
40
|
+
|
35
41
|
private
|
36
42
|
def read_entry(key, **s)
|
37
43
|
deserialize_entry(read_serialized_entry(key))
|