activesupport 6.1.4.1 → 7.0.0.alpha1
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 +151 -526
- data/MIT-LICENSE +1 -1
- data/lib/active_support/actionable_error.rb +1 -1
- data/lib/active_support/array_inquirer.rb +0 -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 +119 -28
- data/lib/active_support/cache/memory_store.rb +21 -13
- data/lib/active_support/cache/null_store.rb +10 -2
- data/lib/active_support/cache/redis_cache_store.rb +39 -59
- data/lib/active_support/cache/strategy/local_cache.rb +29 -49
- data/lib/active_support/cache.rb +189 -45
- data/lib/active_support/callbacks.rb +35 -31
- 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 +6 -3
- 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 +6 -6
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +2 -2
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/digest/uuid.rb +13 -12
- data/lib/active_support/core_ext/enumerable.rb +64 -12
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- 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/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 +2 -2
- 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 +29 -24
- 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/range/compare_range.rb +0 -25
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +1 -1
- 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/output_safety.rb +60 -36
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
- data/lib/active_support/core_ext/time/calculations.rb +6 -5
- data/lib/active_support/core_ext/time/zones.rb +2 -17
- data/lib/active_support/core_ext/uri.rb +1 -15
- data/lib/active_support/current_attributes.rb +17 -1
- 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 +4 -1
- data/lib/active_support/deprecation/method_wrappers.rb +3 -3
- data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/descendants_tracker.rb +12 -9
- data/lib/active_support/digest.rb +5 -3
- 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 +11 -1
- data/lib/active_support/encrypted_file.rb +1 -1
- data/lib/active_support/environment_inquirer.rb +1 -1
- data/lib/active_support/evented_file_update_checker.rb +1 -1
- data/lib/active_support/fork_tracker.rb +2 -4
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +3 -1
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/inflector/inflections.rb +11 -4
- data/lib/active_support/inflector/methods.rb +23 -47
- data/lib/active_support/json/encoding.rb +3 -3
- data/lib/active_support/key_generator.rb +18 -1
- data/lib/active_support/locale/en.yml +1 -1
- data/lib/active_support/log_subscriber.rb +13 -3
- data/lib/active_support/logger_thread_safe_level.rb +5 -13
- data/lib/active_support/message_encryptor.rb +3 -3
- data/lib/active_support/message_verifier.rb +4 -4
- 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 +2 -2
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +31 -11
- data/lib/active_support/notifications/instrumenter.rb +17 -0
- data/lib/active_support/notifications.rb +10 -0
- 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 +4 -16
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/parameter_filter.rb +5 -0
- data/lib/active_support/per_thread_registry.rb +1 -0
- data/lib/active_support/railtie.rb +34 -11
- data/lib/active_support/rescuable.rb +2 -2
- data/lib/active_support/secure_compare_rotator.rb +1 -1
- data/lib/active_support/string_inquirer.rb +0 -2
- data/lib/active_support/subscriber.rb +5 -0
- data/lib/active_support/tagged_logging.rb +1 -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 +1 -1
- data/lib/active_support/testing/isolation.rb +1 -1
- 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 +19 -6
- data/lib/active_support/values/time_zone.rb +25 -9
- 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 +2 -1
- data/lib/active_support.rb +14 -1
- metadata +14 -28
- data/lib/active_support/core_ext/marshal.rb +0 -26
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -34,57 +34,40 @@ module ActiveSupport
|
|
34
34
|
|
35
35
|
# Simple memory backed cache. This cache is not thread safe and is intended only
|
36
36
|
# for serving as a temporary memory cache for a single thread.
|
37
|
-
class LocalStore
|
37
|
+
class LocalStore
|
38
38
|
def initialize
|
39
|
-
super
|
40
39
|
@data = {}
|
41
40
|
end
|
42
41
|
|
43
|
-
# Don't allow synchronizing since it isn't thread safe.
|
44
|
-
def synchronize # :nodoc:
|
45
|
-
yield
|
46
|
-
end
|
47
|
-
|
48
42
|
def clear(options = nil)
|
49
43
|
@data.clear
|
50
44
|
end
|
51
45
|
|
52
|
-
def read_entry(key
|
46
|
+
def read_entry(key)
|
53
47
|
@data[key]
|
54
48
|
end
|
55
49
|
|
56
|
-
def read_multi_entries(keys
|
57
|
-
|
58
|
-
|
59
|
-
keys.each do |name|
|
60
|
-
entry = read_entry(name, **options)
|
61
|
-
values[name] = entry.value if entry
|
62
|
-
end
|
63
|
-
|
64
|
-
values
|
50
|
+
def read_multi_entries(keys)
|
51
|
+
@data.slice(*keys)
|
65
52
|
end
|
66
53
|
|
67
|
-
def write_entry(key, entry
|
68
|
-
entry.dup_value!
|
54
|
+
def write_entry(key, entry)
|
69
55
|
@data[key] = entry
|
70
56
|
true
|
71
57
|
end
|
72
58
|
|
73
|
-
def delete_entry(key
|
59
|
+
def delete_entry(key)
|
74
60
|
!!@data.delete(key)
|
75
61
|
end
|
76
62
|
|
77
|
-
def fetch_entry(key
|
78
|
-
|
79
|
-
dup_entry = entry.dup
|
80
|
-
dup_entry&.dup_value!
|
81
|
-
dup_entry
|
63
|
+
def fetch_entry(key) # :nodoc:
|
64
|
+
@data.fetch(key) { @data[key] = yield }
|
82
65
|
end
|
83
66
|
end
|
84
67
|
|
85
68
|
# Use a local cache for the duration of block.
|
86
|
-
def with_local_cache
|
87
|
-
use_temporary_local_cache(LocalStore.new)
|
69
|
+
def with_local_cache(&block)
|
70
|
+
use_temporary_local_cache(LocalStore.new, &block)
|
88
71
|
end
|
89
72
|
|
90
73
|
# Middleware class can be inserted as a Rack handler to be local cache for the
|
@@ -116,27 +99,27 @@ module ActiveSupport
|
|
116
99
|
def increment(name, amount = 1, **options) # :nodoc:
|
117
100
|
return super unless local_cache
|
118
101
|
value = bypass_local_cache { super }
|
119
|
-
write_cache_value(name, value, **options)
|
102
|
+
write_cache_value(name, value, raw: true, **options)
|
120
103
|
value
|
121
104
|
end
|
122
105
|
|
123
106
|
def decrement(name, amount = 1, **options) # :nodoc:
|
124
107
|
return super unless local_cache
|
125
108
|
value = bypass_local_cache { super }
|
126
|
-
write_cache_value(name, value, **options)
|
109
|
+
write_cache_value(name, value, raw: true, **options)
|
127
110
|
value
|
128
111
|
end
|
129
112
|
|
130
113
|
private
|
131
|
-
def
|
114
|
+
def read_serialized_entry(key, raw: false, **options)
|
132
115
|
if cache = local_cache
|
133
116
|
hit = true
|
134
|
-
|
117
|
+
entry = cache.fetch_entry(key) do
|
135
118
|
hit = false
|
136
119
|
super
|
137
120
|
end
|
138
121
|
options[:event][:store] = cache.class.name if hit && options[:event]
|
139
|
-
|
122
|
+
entry
|
140
123
|
else
|
141
124
|
super
|
142
125
|
end
|
@@ -145,7 +128,7 @@ module ActiveSupport
|
|
145
128
|
def read_multi_entries(keys, **options)
|
146
129
|
return super unless local_cache
|
147
130
|
|
148
|
-
local_entries = local_cache.read_multi_entries(keys
|
131
|
+
local_entries = local_cache.read_multi_entries(keys)
|
149
132
|
missed_keys = keys - local_entries.keys
|
150
133
|
|
151
134
|
if missed_keys.any?
|
@@ -155,30 +138,27 @@ module ActiveSupport
|
|
155
138
|
end
|
156
139
|
end
|
157
140
|
|
158
|
-
def
|
159
|
-
if
|
160
|
-
local_cache.
|
141
|
+
def write_serialized_entry(key, payload, **)
|
142
|
+
if return_value = super
|
143
|
+
local_cache.write_entry(key, payload) if local_cache
|
161
144
|
else
|
162
|
-
local_cache.
|
145
|
+
local_cache.delete_entry(key) if local_cache
|
163
146
|
end
|
164
|
-
|
165
|
-
super
|
147
|
+
return_value
|
166
148
|
end
|
167
149
|
|
168
|
-
def delete_entry(key, **
|
169
|
-
local_cache.delete_entry(key
|
150
|
+
def delete_entry(key, **)
|
151
|
+
local_cache.delete_entry(key) if local_cache
|
170
152
|
super
|
171
153
|
end
|
172
154
|
|
173
155
|
def write_cache_value(name, value, **options)
|
174
156
|
name = normalize_key(name, options)
|
175
157
|
cache = local_cache
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
cache.delete(name, **options)
|
181
|
-
end
|
158
|
+
if value
|
159
|
+
cache.write_entry(name, serialize_entry(new_entry(value, **options), **options))
|
160
|
+
else
|
161
|
+
cache.delete_entry(name)
|
182
162
|
end
|
183
163
|
end
|
184
164
|
|
@@ -190,8 +170,8 @@ module ActiveSupport
|
|
190
170
|
LocalCacheRegistry.cache_for(local_cache_key)
|
191
171
|
end
|
192
172
|
|
193
|
-
def bypass_local_cache
|
194
|
-
use_temporary_local_cache(nil)
|
173
|
+
def bypass_local_cache(&block)
|
174
|
+
use_temporary_local_cache(nil, &block)
|
195
175
|
end
|
196
176
|
|
197
177
|
def use_temporary_local_cache(temporary_cache)
|
data/lib/active_support/cache.rb
CHANGED
@@ -22,13 +22,24 @@ module ActiveSupport
|
|
22
22
|
|
23
23
|
# These options mean something to all cache implementations. Individual cache
|
24
24
|
# implementations may support additional options.
|
25
|
-
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl, :coder]
|
25
|
+
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :expire_in, :expired_in, :race_condition_ttl, :coder, :skip_nil]
|
26
|
+
|
27
|
+
DEFAULT_COMPRESS_LIMIT = 1.kilobyte
|
28
|
+
|
29
|
+
# Mapping of canonical option names to aliases that a store will recognize.
|
30
|
+
OPTION_ALIASES = {
|
31
|
+
expires_in: [:expire_in, :expired_in]
|
32
|
+
}.freeze
|
26
33
|
|
27
34
|
module Strategy
|
28
35
|
autoload :LocalCache, "active_support/cache/strategy/local_cache"
|
29
36
|
end
|
30
37
|
|
38
|
+
@format_version = 6.1
|
39
|
+
|
31
40
|
class << self
|
41
|
+
attr_accessor :format_version
|
42
|
+
|
32
43
|
# Creates a new Store object according to the given options.
|
33
44
|
#
|
34
45
|
# If no arguments are passed to this method, then a new
|
@@ -164,8 +175,6 @@ module ActiveSupport
|
|
164
175
|
# threshold is configurable with the <tt>:compress_threshold</tt> option,
|
165
176
|
# specified in bytes.
|
166
177
|
class Store
|
167
|
-
DEFAULT_CODER = Marshal
|
168
|
-
|
169
178
|
cattr_accessor :logger, instance_writer: true
|
170
179
|
|
171
180
|
attr_reader :silence, :options
|
@@ -192,8 +201,12 @@ module ActiveSupport
|
|
192
201
|
# except for <tt>:namespace</tt> which can be used to set the global
|
193
202
|
# namespace for the cache.
|
194
203
|
def initialize(options = nil)
|
195
|
-
@options = options ? options
|
196
|
-
@
|
204
|
+
@options = options ? normalize_options(options) : {}
|
205
|
+
@options[:compress] = true unless @options.key?(:compress)
|
206
|
+
@options[:compress_threshold] = DEFAULT_COMPRESS_LIMIT unless @options.key?(:compress_threshold)
|
207
|
+
|
208
|
+
@coder = @options.delete(:coder) { default_coder } || NullCoder
|
209
|
+
@coder_supports_compression = @coder.respond_to?(:dump_compressed)
|
197
210
|
end
|
198
211
|
|
199
212
|
# Silences the logger.
|
@@ -255,11 +268,21 @@ module ActiveSupport
|
|
255
268
|
# All caches support auto-expiring content after a specified number of
|
256
269
|
# seconds. This value can be specified as an option to the constructor
|
257
270
|
# (in which case all entries will be affected), or it can be supplied to
|
258
|
-
# the +fetch+ or +write+ method to
|
271
|
+
# the +fetch+ or +write+ method to affect just one entry.
|
272
|
+
# <tt>:expire_in</tt> and <tt>:expired_in</tt> are aliases for
|
273
|
+
# <tt>:expires_in</tt>.
|
259
274
|
#
|
260
275
|
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
|
261
276
|
# cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
|
262
277
|
#
|
278
|
+
# Setting <tt>:expires_at</tt> will set an absolute expiration time on the cache.
|
279
|
+
# All caches support auto-expiring content after a specified number of
|
280
|
+
# seconds. This value can only be supplied to the +fetch+ or +write+ method to
|
281
|
+
# affect just one entry.
|
282
|
+
#
|
283
|
+
# cache = ActiveSupport::Cache::MemoryStore.new
|
284
|
+
# cache.write(key, value, expires_at: Time.now.at_end_of_hour)
|
285
|
+
#
|
263
286
|
# Setting <tt>:version</tt> verifies the cache stored under <tt>name</tt>
|
264
287
|
# is of the same version. nil is returned on mismatches despite contents.
|
265
288
|
# This feature is used to support recyclable cache keys.
|
@@ -512,6 +535,10 @@ module ActiveSupport
|
|
512
535
|
end
|
513
536
|
end
|
514
537
|
|
538
|
+
def new_entry(value, options = nil) # :nodoc:
|
539
|
+
Entry.new(value, **merged_options(options))
|
540
|
+
end
|
541
|
+
|
515
542
|
# Deletes all entries with keys matching the pattern.
|
516
543
|
#
|
517
544
|
# Options are passed to the underlying cache implementation.
|
@@ -559,6 +586,10 @@ module ActiveSupport
|
|
559
586
|
end
|
560
587
|
|
561
588
|
private
|
589
|
+
def default_coder
|
590
|
+
Coders[Cache.format_version]
|
591
|
+
end
|
592
|
+
|
562
593
|
# Adds the namespace defined in the options to a pattern designed to
|
563
594
|
# match keys. Implementations that support delete_matched should call
|
564
595
|
# this method to translate a pattern that matches names into one that
|
@@ -590,8 +621,13 @@ module ActiveSupport
|
|
590
621
|
raise NotImplementedError.new
|
591
622
|
end
|
592
623
|
|
593
|
-
def serialize_entry(entry)
|
594
|
-
|
624
|
+
def serialize_entry(entry, **options)
|
625
|
+
options = merged_options(options)
|
626
|
+
if @coder_supports_compression && options[:compress]
|
627
|
+
@coder.dump_compressed(entry, options[:compress_threshold] || DEFAULT_COMPRESS_LIMIT)
|
628
|
+
else
|
629
|
+
@coder.dump(entry)
|
630
|
+
end
|
595
631
|
end
|
596
632
|
|
597
633
|
def deserialize_entry(payload)
|
@@ -640,6 +676,7 @@ module ActiveSupport
|
|
640
676
|
# Merges the default options with ones specific to a method call.
|
641
677
|
def merged_options(call_options)
|
642
678
|
if call_options
|
679
|
+
call_options = normalize_options(call_options)
|
643
680
|
if options.empty?
|
644
681
|
call_options
|
645
682
|
else
|
@@ -650,6 +687,18 @@ module ActiveSupport
|
|
650
687
|
end
|
651
688
|
end
|
652
689
|
|
690
|
+
# Normalize aliased options to their canonical form
|
691
|
+
def normalize_options(options)
|
692
|
+
options = options.dup
|
693
|
+
OPTION_ALIASES.each do |canonical_name, aliases|
|
694
|
+
alias_key = aliases.detect { |key| options.key?(key) }
|
695
|
+
options[canonical_name] ||= options[alias_key] if alias_key
|
696
|
+
options.except!(*aliases)
|
697
|
+
end
|
698
|
+
|
699
|
+
options
|
700
|
+
end
|
701
|
+
|
653
702
|
# Expands and namespaces the cache key. May be overridden by
|
654
703
|
# cache stores to do additional normalization.
|
655
704
|
def normalize_key(key, options = nil)
|
@@ -732,7 +781,7 @@ module ActiveSupport
|
|
732
781
|
if (race_ttl > 0) && (Time.now.to_f - entry.expires_at <= race_ttl)
|
733
782
|
# When an entry has a positive :race_condition_ttl defined, put the stale entry back into the cache
|
734
783
|
# for a brief period while the entry is being recalculated.
|
735
|
-
entry.expires_at = Time.now + race_ttl
|
784
|
+
entry.expires_at = Time.now.to_f + race_ttl
|
736
785
|
write_entry(key, entry, expires_in: race_ttl * 2)
|
737
786
|
else
|
738
787
|
delete_entry(key, **options)
|
@@ -758,13 +807,93 @@ module ActiveSupport
|
|
758
807
|
end
|
759
808
|
|
760
809
|
module NullCoder # :nodoc:
|
810
|
+
extend self
|
811
|
+
|
812
|
+
def dump(entry)
|
813
|
+
entry
|
814
|
+
end
|
815
|
+
|
816
|
+
def dump_compressed(entry, threshold)
|
817
|
+
entry.compressed(threshold)
|
818
|
+
end
|
819
|
+
|
820
|
+
def load(payload)
|
821
|
+
payload
|
822
|
+
end
|
823
|
+
end
|
824
|
+
|
825
|
+
module Coders # :nodoc:
|
826
|
+
MARK_61 = "\x04\b".b.freeze # The one set by Marshal.
|
827
|
+
MARK_70_UNCOMPRESSED = "\x00".b.freeze
|
828
|
+
MARK_70_COMPRESSED = "\x01".b.freeze
|
829
|
+
|
761
830
|
class << self
|
831
|
+
def [](version)
|
832
|
+
case version
|
833
|
+
when 6.1
|
834
|
+
Rails61Coder
|
835
|
+
when 7.0
|
836
|
+
Rails70Coder
|
837
|
+
else
|
838
|
+
raise ArgumentError, "Unknown ActiveSupport::Cache.format_version #{Cache.format_version.inspect}"
|
839
|
+
end
|
840
|
+
end
|
841
|
+
end
|
842
|
+
|
843
|
+
module Loader
|
844
|
+
extend self
|
845
|
+
|
762
846
|
def load(payload)
|
763
|
-
payload
|
847
|
+
if !payload.is_a?(String)
|
848
|
+
ActiveSupport::Cache::Store.logger&.warn %{Payload wasn't a string, was #{payload.class.name} - couldn't unmarshal, so returning nil."}
|
849
|
+
|
850
|
+
return nil
|
851
|
+
elsif payload.start_with?(MARK_70_UNCOMPRESSED)
|
852
|
+
members = Marshal.load(payload.byteslice(1..-1))
|
853
|
+
elsif payload.start_with?(MARK_70_COMPRESSED)
|
854
|
+
members = Marshal.load(Zlib::Inflate.inflate(payload.byteslice(1..-1)))
|
855
|
+
elsif payload.start_with?(MARK_61)
|
856
|
+
return Marshal.load(payload)
|
857
|
+
else
|
858
|
+
ActiveSupport::Cache::Store.logger&.warn %{Invalid cache prefix: #{payload.byteslice(0).inspect}, expected "\\x00" or "\\x01"}
|
859
|
+
|
860
|
+
return nil
|
861
|
+
end
|
862
|
+
Entry.unpack(members)
|
764
863
|
end
|
864
|
+
end
|
865
|
+
|
866
|
+
module Rails61Coder
|
867
|
+
include Loader
|
868
|
+
extend self
|
765
869
|
|
766
870
|
def dump(entry)
|
767
|
-
entry
|
871
|
+
Marshal.dump(entry)
|
872
|
+
end
|
873
|
+
|
874
|
+
def dump_compressed(entry, threshold)
|
875
|
+
Marshal.dump(entry.compressed(threshold))
|
876
|
+
end
|
877
|
+
end
|
878
|
+
|
879
|
+
module Rails70Coder
|
880
|
+
include Loader
|
881
|
+
extend self
|
882
|
+
|
883
|
+
def dump(entry)
|
884
|
+
MARK_70_UNCOMPRESSED + Marshal.dump(entry.pack)
|
885
|
+
end
|
886
|
+
|
887
|
+
def dump_compressed(entry, threshold)
|
888
|
+
payload = Marshal.dump(entry.pack)
|
889
|
+
if payload.bytesize >= threshold
|
890
|
+
compressed_payload = Zlib::Deflate.deflate(payload)
|
891
|
+
if compressed_payload.bytesize < payload.bytesize
|
892
|
+
return MARK_70_COMPRESSED + compressed_payload
|
893
|
+
end
|
894
|
+
end
|
895
|
+
|
896
|
+
MARK_70_UNCOMPRESSED + payload
|
768
897
|
end
|
769
898
|
end
|
770
899
|
end
|
@@ -777,19 +906,22 @@ module ActiveSupport
|
|
777
906
|
# Since cache entries in most instances will be serialized, the internals of this class are highly optimized
|
778
907
|
# using short instance variable names that are lazily defined.
|
779
908
|
class Entry # :nodoc:
|
780
|
-
|
909
|
+
class << self
|
910
|
+
def unpack(members)
|
911
|
+
new(members[0], expires_at: members[1], version: members[2])
|
912
|
+
end
|
913
|
+
end
|
781
914
|
|
782
|
-
|
915
|
+
attr_reader :version
|
783
916
|
|
784
917
|
# Creates a new cache entry for the specified value. Options supported are
|
785
|
-
# +:
|
786
|
-
def initialize(value,
|
918
|
+
# +:compressed+, +:version+, +:expires_at+ and +:expires_in+.
|
919
|
+
def initialize(value, compressed: false, version: nil, expires_in: nil, expires_at: nil, **)
|
787
920
|
@value = value
|
788
921
|
@version = version
|
789
|
-
@created_at =
|
790
|
-
@expires_in = expires_in && expires_in.to_f
|
791
|
-
|
792
|
-
compress!(compress_threshold) if compress
|
922
|
+
@created_at = 0.0
|
923
|
+
@expires_in = expires_at&.to_f || expires_in && (expires_in.to_f + Time.now.to_f)
|
924
|
+
@compressed = true if compressed
|
793
925
|
end
|
794
926
|
|
795
927
|
def value
|
@@ -831,6 +963,38 @@ module ActiveSupport
|
|
831
963
|
end
|
832
964
|
end
|
833
965
|
|
966
|
+
def compressed? # :nodoc:
|
967
|
+
defined?(@compressed)
|
968
|
+
end
|
969
|
+
|
970
|
+
def compressed(compress_threshold)
|
971
|
+
return self if compressed?
|
972
|
+
|
973
|
+
case @value
|
974
|
+
when nil, true, false, Numeric
|
975
|
+
uncompressed_size = 0
|
976
|
+
when String
|
977
|
+
uncompressed_size = @value.bytesize
|
978
|
+
else
|
979
|
+
serialized = Marshal.dump(@value)
|
980
|
+
uncompressed_size = serialized.bytesize
|
981
|
+
end
|
982
|
+
|
983
|
+
if uncompressed_size >= compress_threshold
|
984
|
+
serialized ||= Marshal.dump(@value)
|
985
|
+
compressed = Zlib::Deflate.deflate(serialized)
|
986
|
+
|
987
|
+
if compressed.bytesize < uncompressed_size
|
988
|
+
return Entry.new(compressed, compressed: true, expires_at: expires_at, version: version)
|
989
|
+
end
|
990
|
+
end
|
991
|
+
self
|
992
|
+
end
|
993
|
+
|
994
|
+
def local?
|
995
|
+
false
|
996
|
+
end
|
997
|
+
|
834
998
|
# Duplicates the value in a class. This is used by cache implementations that don't natively
|
835
999
|
# serialize entries to protect against accidental cache modifications.
|
836
1000
|
def dup_value!
|
@@ -843,33 +1007,13 @@ module ActiveSupport
|
|
843
1007
|
end
|
844
1008
|
end
|
845
1009
|
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
when String
|
852
|
-
uncompressed_size = @value.bytesize
|
853
|
-
else
|
854
|
-
serialized = Marshal.dump(@value)
|
855
|
-
uncompressed_size = serialized.bytesize
|
856
|
-
end
|
857
|
-
|
858
|
-
if uncompressed_size >= compress_threshold
|
859
|
-
serialized ||= Marshal.dump(@value)
|
860
|
-
compressed = Zlib::Deflate.deflate(serialized)
|
861
|
-
|
862
|
-
if compressed.bytesize < uncompressed_size
|
863
|
-
@value = compressed
|
864
|
-
@compressed = true
|
865
|
-
end
|
866
|
-
end
|
867
|
-
end
|
868
|
-
|
869
|
-
def compressed?
|
870
|
-
defined?(@compressed)
|
871
|
-
end
|
1010
|
+
def pack
|
1011
|
+
members = [value, expires_at, version]
|
1012
|
+
members.pop while !members.empty? && members.last.nil?
|
1013
|
+
members
|
1014
|
+
end
|
872
1015
|
|
1016
|
+
private
|
873
1017
|
def uncompress(value)
|
874
1018
|
Marshal.load(Zlib::Inflate.inflate(value))
|
875
1019
|
end
|