activesupport 4.2.11.1 → 5.2.4
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 +399 -440
- data/MIT-LICENSE +2 -2
- data/README.rdoc +4 -5
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +7 -5
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +41 -35
- data/lib/active_support/cache/mem_cache_store.rb +97 -88
- data/lib/active_support/cache/memory_store.rb +27 -30
- data/lib/active_support/cache/null_store.rb +7 -8
- data/lib/active_support/cache/redis_cache_store.rb +461 -0
- data/lib/active_support/cache/strategy/local_cache.rb +67 -34
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +287 -196
- data/lib/active_support/callbacks.rb +640 -590
- data/lib/active_support/concern.rb +11 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
- data/lib/active_support/concurrency/share_lock.rb +227 -0
- data/lib/active_support/configurable.rb +8 -5
- data/lib/active_support/core_ext/array/access.rb +29 -1
- data/lib/active_support/core_ext/array/conversions.rb +22 -18
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +41 -22
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +20 -6
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +11 -9
- data/lib/active_support/core_ext/date/conversions.rb +25 -23
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +170 -58
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +36 -18
- data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +101 -33
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/compact.rb +14 -9
- data/lib/active_support/core_ext/hash/conversions.rb +62 -41
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/except.rb +11 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +33 -27
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -8
- data/lib/active_support/core_ext/hash/transform_values.rb +14 -5
- data/lib/active_support/core_ext/hash.rb +11 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +2 -0
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +6 -5
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +8 -8
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
- data/lib/active_support/core_ext/module/concerning.rb +11 -12
- data/lib/active_support/core_ext/module/delegation.rb +99 -29
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +9 -9
- data/lib/active_support/core_ext/module/reachable.rb +5 -2
- data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +14 -11
- data/lib/active_support/core_ext/name_error.rb +22 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +78 -81
- data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
- data/lib/active_support/core_ext/numeric/time.rb +35 -23
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +27 -2
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +41 -14
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +49 -19
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +69 -21
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/range/compare_range.rb +61 -0
- data/lib/active_support/core_ext/range/conversions.rb +27 -7
- data/lib/active_support/core_ext/range/each.rb +19 -17
- data/lib/active_support/core_ext/range/include_range.rb +2 -22
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +6 -0
- data/lib/active_support/core_ext/securerandom.rb +25 -0
- data/lib/active_support/core_ext/string/access.rb +8 -6
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +7 -4
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +6 -5
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +61 -24
- data/lib/active_support/core_ext/string/inquiry.rb +3 -1
- data/lib/active_support/core_ext/string/multibyte.rb +15 -7
- data/lib/active_support/core_ext/string/output_safety.rb +34 -38
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +4 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +85 -51
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +20 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/time.rb +7 -6
- data/lib/active_support/core_ext/uri.rb +6 -8
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies.rb +152 -161
- data/lib/active_support/deprecation/behaviors.rb +44 -11
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/instance_delegator.rb +17 -2
- data/lib/active_support/deprecation/method_wrappers.rb +66 -20
- data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/deprecation.rb +12 -9
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +125 -0
- data/lib/active_support/duration/iso8601_serializer.rb +55 -0
- data/lib/active_support/duration.rb +307 -35
- data/lib/active_support/encrypted_configuration.rb +49 -0
- data/lib/active_support/encrypted_file.rb +99 -0
- data/lib/active_support/evented_file_update_checker.rb +205 -0
- data/lib/active_support/execution_wrapper.rb +128 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +63 -37
- data/lib/active_support/gem_version.rb +6 -4
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +123 -28
- data/lib/active_support/i18n.rb +8 -6
- data/lib/active_support/i18n_railtie.rb +37 -13
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +61 -12
- data/lib/active_support/inflector/methods.rb +163 -136
- data/lib/active_support/inflector/transliterate.rb +48 -27
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +16 -13
- data/lib/active_support/json/encoding.rb +11 -58
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +25 -25
- data/lib/active_support/lazy_load_hooks.rb +50 -20
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +13 -10
- data/lib/active_support/logger.rb +8 -7
- data/lib/active_support/logger_silence.rb +6 -4
- data/lib/active_support/logger_thread_safe_level.rb +7 -5
- data/lib/active_support/message_encryptor.rb +168 -53
- data/lib/active_support/message_verifier.rb +150 -17
- data/lib/active_support/messages/metadata.rb +71 -0
- data/lib/active_support/messages/rotation_configuration.rb +22 -0
- data/lib/active_support/messages/rotator.rb +56 -0
- data/lib/active_support/multibyte/chars.rb +36 -23
- data/lib/active_support/multibyte/unicode.rb +100 -96
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +11 -9
- data/lib/active_support/notifications/instrumenter.rb +27 -7
- data/lib/active_support/notifications.rb +11 -7
- data/lib/active_support/number_helper/number_converter.rb +13 -11
- data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/number_helper.rb +94 -68
- data/lib/active_support/option_merger.rb +3 -1
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +23 -5
- data/lib/active_support/per_thread_registry.rb +9 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +16 -8
- data/lib/active_support/railtie.rb +43 -9
- data/lib/active_support/reloader.rb +131 -0
- data/lib/active_support/rescuable.rb +108 -53
- data/lib/active_support/security_utils.rb +15 -11
- data/lib/active_support/string_inquirer.rb +11 -3
- data/lib/active_support/subscriber.rb +21 -16
- data/lib/active_support/tagged_logging.rb +14 -11
- data/lib/active_support/test_case.rb +19 -47
- data/lib/active_support/testing/assertions.rb +137 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +14 -10
- data/lib/active_support/testing/file_fixtures.rb +36 -0
- data/lib/active_support/testing/isolation.rb +34 -25
- data/lib/active_support/testing/method_call_assertions.rb +43 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +44 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +81 -15
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +169 -39
- data/lib/active_support/values/time_zone.rb +196 -61
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +116 -114
- data/lib/active_support/xml_mini/libxml.rb +16 -13
- data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
- data/lib/active_support/xml_mini/nokogiri.rb +14 -12
- data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
- data/lib/active_support/xml_mini/rexml.rb +11 -9
- data/lib/active_support/xml_mini.rb +37 -37
- data/lib/active_support.rb +12 -11
- metadata +54 -24
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
data/lib/active_support/cache.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require 'active_support/deprecation'
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zlib"
|
4
|
+
require "active_support/core_ext/array/extract_options"
|
5
|
+
require "active_support/core_ext/array/wrap"
|
6
|
+
require "active_support/core_ext/module/attribute_accessors"
|
7
|
+
require "active_support/core_ext/numeric/bytes"
|
8
|
+
require "active_support/core_ext/numeric/time"
|
9
|
+
require "active_support/core_ext/object/to_param"
|
10
|
+
require "active_support/core_ext/string/inflections"
|
12
11
|
|
13
12
|
module ActiveSupport
|
14
13
|
# See ActiveSupport::Cache::Store for documentation.
|
15
14
|
module Cache
|
16
|
-
autoload :FileStore,
|
17
|
-
autoload :MemoryStore,
|
18
|
-
autoload :MemCacheStore,
|
19
|
-
autoload :NullStore,
|
15
|
+
autoload :FileStore, "active_support/cache/file_store"
|
16
|
+
autoload :MemoryStore, "active_support/cache/memory_store"
|
17
|
+
autoload :MemCacheStore, "active_support/cache/mem_cache_store"
|
18
|
+
autoload :NullStore, "active_support/cache/null_store"
|
19
|
+
autoload :RedisCacheStore, "active_support/cache/redis_cache_store"
|
20
20
|
|
21
21
|
# These options mean something to all cache implementations. Individual cache
|
22
22
|
# implementations may support additional options.
|
23
23
|
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl]
|
24
24
|
|
25
25
|
module Strategy
|
26
|
-
autoload :LocalCache,
|
26
|
+
autoload :LocalCache, "active_support/cache/strategy/local_cache"
|
27
27
|
end
|
28
28
|
|
29
29
|
class << self
|
@@ -73,12 +73,12 @@ module ActiveSupport
|
|
73
73
|
# each of elements in the array will be turned into parameters/keys and
|
74
74
|
# concatenated into a single key. For example:
|
75
75
|
#
|
76
|
-
# expand_cache_key([:foo, :bar]) # => "foo/bar"
|
77
|
-
# expand_cache_key([:foo, :bar], "namespace") # => "namespace/foo/bar"
|
76
|
+
# ActiveSupport::Cache.expand_cache_key([:foo, :bar]) # => "foo/bar"
|
77
|
+
# ActiveSupport::Cache.expand_cache_key([:foo, :bar], "namespace") # => "namespace/foo/bar"
|
78
78
|
#
|
79
79
|
# The +key+ argument can also respond to +cache_key+ or +to_param+.
|
80
80
|
def expand_cache_key(key, namespace = nil)
|
81
|
-
expanded_cache_key = namespace ? "#{namespace}/" : ""
|
81
|
+
expanded_cache_key = (namespace ? "#{namespace}/" : "").dup
|
82
82
|
|
83
83
|
if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
|
84
84
|
expanded_cache_key << "#{prefix}/"
|
@@ -91,16 +91,19 @@ module ActiveSupport
|
|
91
91
|
private
|
92
92
|
def retrieve_cache_key(key)
|
93
93
|
case
|
94
|
-
when key.respond_to?(:
|
95
|
-
when key.
|
96
|
-
when key.
|
97
|
-
|
94
|
+
when key.respond_to?(:cache_key_with_version) then key.cache_key_with_version
|
95
|
+
when key.respond_to?(:cache_key) then key.cache_key
|
96
|
+
when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param
|
97
|
+
when key.respond_to?(:to_a) then retrieve_cache_key(key.to_a)
|
98
|
+
else key.to_param
|
98
99
|
end.to_s
|
99
100
|
end
|
100
101
|
|
101
102
|
# Obtains the specified cache store class, given the name of the +store+.
|
102
103
|
# Raises an error when the store class cannot be found.
|
103
104
|
def retrieve_store_class(store)
|
105
|
+
# require_relative cannot be used here because the class might be
|
106
|
+
# provided by another gem, like redis-activesupport for example.
|
104
107
|
require "active_support/cache/#{store}"
|
105
108
|
rescue LoadError => e
|
106
109
|
raise "Could not find cache store adapter for #{store} (#{e})"
|
@@ -146,32 +149,48 @@ module ActiveSupport
|
|
146
149
|
# cache.namespace = -> { @last_mod_time } # Set the namespace to a variable
|
147
150
|
# @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
|
148
151
|
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
# <tt
|
153
|
-
#
|
154
|
-
# <tt>:compress_threshold</tt> option. The default threshold is 16K.
|
152
|
+
# Cached data larger than 1kB are compressed by default. To turn off
|
153
|
+
# compression, pass <tt>compress: false</tt> to the initializer or to
|
154
|
+
# individual +fetch+ or +write+ method calls. The 1kB compression
|
155
|
+
# threshold is configurable with the <tt>:compress_threshold</tt> option,
|
156
|
+
# specified in bytes.
|
155
157
|
class Store
|
156
|
-
cattr_accessor :logger, :
|
158
|
+
cattr_accessor :logger, instance_writer: true
|
157
159
|
|
158
160
|
attr_reader :silence, :options
|
159
161
|
alias :silence? :silence
|
160
162
|
|
161
|
-
|
163
|
+
class << self
|
164
|
+
private
|
165
|
+
def retrieve_pool_options(options)
|
166
|
+
{}.tap do |pool_options|
|
167
|
+
pool_options[:size] = options.delete(:pool_size) if options[:pool_size]
|
168
|
+
pool_options[:timeout] = options.delete(:pool_timeout) if options[:pool_timeout]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def ensure_connection_pool_added!
|
173
|
+
require "connection_pool"
|
174
|
+
rescue LoadError => e
|
175
|
+
$stderr.puts "You don't have connection_pool installed in your application. Please add it to your Gemfile and run bundle install"
|
176
|
+
raise e
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Creates a new cache. The options will be passed to any write method calls
|
162
181
|
# except for <tt>:namespace</tt> which can be used to set the global
|
163
182
|
# namespace for the cache.
|
164
183
|
def initialize(options = nil)
|
165
184
|
@options = options ? options.dup : {}
|
166
185
|
end
|
167
186
|
|
168
|
-
#
|
187
|
+
# Silences the logger.
|
169
188
|
def silence!
|
170
189
|
@silence = true
|
171
190
|
self
|
172
191
|
end
|
173
192
|
|
174
|
-
#
|
193
|
+
# Silences the logger within a block.
|
175
194
|
def mute
|
176
195
|
previous_silence, @silence = defined?(@silence) && @silence, true
|
177
196
|
yield
|
@@ -179,18 +198,6 @@ module ActiveSupport
|
|
179
198
|
@silence = previous_silence
|
180
199
|
end
|
181
200
|
|
182
|
-
# :deprecated:
|
183
|
-
def self.instrument=(boolean)
|
184
|
-
ActiveSupport::Deprecation.warn "ActiveSupport::Cache.instrument= is deprecated and will be removed in Rails 5. Instrumentation is now always on so you can safely stop using it."
|
185
|
-
true
|
186
|
-
end
|
187
|
-
|
188
|
-
# :deprecated:
|
189
|
-
def self.instrument
|
190
|
-
ActiveSupport::Deprecation.warn "ActiveSupport::Cache.instrument is deprecated and will be removed in Rails 5. Instrumentation is now always on so you can safely stop using it."
|
191
|
-
true
|
192
|
-
end
|
193
|
-
|
194
201
|
# Fetches data from the cache, using the given key. If there is data in
|
195
202
|
# the cache with the given key, then that data is returned.
|
196
203
|
#
|
@@ -210,13 +217,19 @@ module ActiveSupport
|
|
210
217
|
# cache.fetch('city') # => "Duckburgh"
|
211
218
|
#
|
212
219
|
# You may also specify additional options via the +options+ argument.
|
213
|
-
# Setting <tt>force: true</tt>
|
220
|
+
# Setting <tt>force: true</tt> forces a cache "miss," meaning we treat
|
221
|
+
# the cache value as missing even if it's present. Passing a block is
|
222
|
+
# required when +force+ is true so this always results in a cache write.
|
214
223
|
#
|
215
224
|
# cache.write('today', 'Monday')
|
216
|
-
# cache.fetch('today', force: true)
|
225
|
+
# cache.fetch('today', force: true) { 'Tuesday' } # => 'Tuesday'
|
226
|
+
# cache.fetch('today', force: true) # => ArgumentError
|
227
|
+
#
|
228
|
+
# The +:force+ option is useful when you're calling some other method to
|
229
|
+
# ask whether you should force a cache write. Otherwise, it's clearer to
|
230
|
+
# just call <tt>Cache#write</tt>.
|
217
231
|
#
|
218
|
-
# Setting <tt
|
219
|
-
# in a compressed format.
|
232
|
+
# Setting <tt>compress: false</tt> disables compression of the cache entry.
|
220
233
|
#
|
221
234
|
# Setting <tt>:expires_in</tt> will set an expiration time on the cache.
|
222
235
|
# All caches support auto-expiring content after a specified number of
|
@@ -227,6 +240,10 @@ module ActiveSupport
|
|
227
240
|
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
|
228
241
|
# cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
|
229
242
|
#
|
243
|
+
# Setting <tt>:version</tt> verifies the cache stored under <tt>name</tt>
|
244
|
+
# is of the same version. nil is returned on mismatches despite contents.
|
245
|
+
# This feature is used to support recyclable cache keys.
|
246
|
+
#
|
230
247
|
# Setting <tt>:race_condition_ttl</tt> is very useful in situations where
|
231
248
|
# a cache entry is used very frequently and is under heavy load. If a
|
232
249
|
# cache expires and due to heavy load several different processes will try
|
@@ -255,22 +272,23 @@ module ActiveSupport
|
|
255
272
|
# sleep 60
|
256
273
|
#
|
257
274
|
# Thread.new do
|
258
|
-
# val_1 = cache.fetch('foo', race_condition_ttl: 10) do
|
275
|
+
# val_1 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
|
259
276
|
# sleep 1
|
260
277
|
# 'new value 1'
|
261
278
|
# end
|
262
279
|
# end
|
263
280
|
#
|
264
281
|
# Thread.new do
|
265
|
-
# val_2 = cache.fetch('foo', race_condition_ttl: 10) do
|
282
|
+
# val_2 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
|
266
283
|
# 'new value 2'
|
267
284
|
# end
|
268
285
|
# end
|
269
286
|
#
|
270
|
-
# #
|
271
|
-
# #
|
272
|
-
#
|
273
|
-
# #
|
287
|
+
# cache.fetch('foo') # => "original value"
|
288
|
+
# sleep 10 # First thread extended the life of cache by another 10 seconds
|
289
|
+
# cache.fetch('foo') # => "new value 1"
|
290
|
+
# val_1 # => "new value 1"
|
291
|
+
# val_2 # => "original value"
|
274
292
|
#
|
275
293
|
# Other options will be handled by the specific cache store implementation.
|
276
294
|
# Internally, #fetch calls #read_entry, and calls #write_entry on a cache
|
@@ -288,36 +306,53 @@ module ActiveSupport
|
|
288
306
|
def fetch(name, options = nil)
|
289
307
|
if block_given?
|
290
308
|
options = merged_options(options)
|
291
|
-
key =
|
309
|
+
key = normalize_key(name, options)
|
292
310
|
|
293
|
-
|
294
|
-
|
311
|
+
entry = nil
|
312
|
+
instrument(:read, name, options) do |payload|
|
313
|
+
cached_entry = read_entry(key, options) unless options[:force]
|
314
|
+
entry = handle_expired_entry(cached_entry, key, options)
|
315
|
+
entry = nil if entry && entry.mismatched?(normalize_version(name, options))
|
316
|
+
payload[:super_operation] = :fetch if payload
|
317
|
+
payload[:hit] = !!entry if payload
|
318
|
+
end
|
295
319
|
|
296
320
|
if entry
|
297
321
|
get_entry_value(entry, name, options)
|
298
322
|
else
|
299
323
|
save_block_result_to_cache(name, options) { |_name| yield _name }
|
300
324
|
end
|
325
|
+
elsif options && options[:force]
|
326
|
+
raise ArgumentError, "Missing block: Calling `Cache#fetch` with `force: true` requires a block."
|
301
327
|
else
|
302
328
|
read(name, options)
|
303
329
|
end
|
304
330
|
end
|
305
331
|
|
306
|
-
#
|
332
|
+
# Reads data from the cache, using the given key. If there is data in
|
307
333
|
# the cache with the given key, then that data is returned. Otherwise,
|
308
334
|
# +nil+ is returned.
|
309
335
|
#
|
336
|
+
# Note, if data was written with the <tt>:expires_in<tt> or <tt>:version</tt> options,
|
337
|
+
# both of these conditions are applied before the data is returned.
|
338
|
+
#
|
310
339
|
# Options are passed to the underlying cache implementation.
|
311
340
|
def read(name, options = nil)
|
312
341
|
options = merged_options(options)
|
313
|
-
key
|
342
|
+
key = normalize_key(name, options)
|
343
|
+
version = normalize_version(name, options)
|
344
|
+
|
314
345
|
instrument(:read, name, options) do |payload|
|
315
346
|
entry = read_entry(key, options)
|
347
|
+
|
316
348
|
if entry
|
317
349
|
if entry.expired?
|
318
350
|
delete_entry(key, options)
|
319
351
|
payload[:hit] = false if payload
|
320
352
|
nil
|
353
|
+
elsif entry.mismatched?(version)
|
354
|
+
payload[:hit] = false if payload
|
355
|
+
nil
|
321
356
|
else
|
322
357
|
payload[:hit] = true if payload
|
323
358
|
entry.value
|
@@ -329,7 +364,7 @@ module ActiveSupport
|
|
329
364
|
end
|
330
365
|
end
|
331
366
|
|
332
|
-
#
|
367
|
+
# Reads multiple values at once from the cache. Options can be passed
|
333
368
|
# in the last argument.
|
334
369
|
#
|
335
370
|
# Some cache implementation may optimize this method.
|
@@ -338,44 +373,64 @@ module ActiveSupport
|
|
338
373
|
def read_multi(*names)
|
339
374
|
options = names.extract_options!
|
340
375
|
options = merged_options(options)
|
341
|
-
|
342
|
-
names
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
376
|
+
|
377
|
+
instrument :read_multi, names, options do |payload|
|
378
|
+
read_multi_entries(names, options).tap do |results|
|
379
|
+
payload[:hits] = results.keys
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
# Cache Storage API to write multiple values at once.
|
385
|
+
def write_multi(hash, options = nil)
|
386
|
+
options = merged_options(options)
|
387
|
+
|
388
|
+
instrument :write_multi, hash, options do |payload|
|
389
|
+
entries = hash.each_with_object({}) do |(name, value), memo|
|
390
|
+
memo[normalize_key(name, options)] = Entry.new(value, options.merge(version: normalize_version(name, options)))
|
351
391
|
end
|
392
|
+
|
393
|
+
write_multi_entries entries, options
|
352
394
|
end
|
353
|
-
results
|
354
395
|
end
|
355
396
|
|
356
397
|
# Fetches data from the cache, using the given keys. If there is data in
|
357
398
|
# the cache with the given keys, then that data is returned. Otherwise,
|
358
399
|
# the supplied block is called for each key for which there was no data,
|
359
400
|
# and the result will be written to the cache and returned.
|
401
|
+
# Therefore, you need to pass a block that returns the data to be written
|
402
|
+
# to the cache. If you do not want to write the cache when the cache is
|
403
|
+
# not found, use #read_multi.
|
360
404
|
#
|
361
405
|
# Options are passed to the underlying cache implementation.
|
362
406
|
#
|
363
407
|
# Returns a hash with the data for each of the names. For example:
|
364
408
|
#
|
365
409
|
# cache.write("bim", "bam")
|
366
|
-
# cache.fetch_multi("bim", "
|
367
|
-
#
|
410
|
+
# cache.fetch_multi("bim", "unknown_key") do |key|
|
411
|
+
# "Fallback value for key: #{key}"
|
412
|
+
# end
|
413
|
+
# # => { "bim" => "bam",
|
414
|
+
# # "unknown_key" => "Fallback value for key: unknown_key" }
|
368
415
|
#
|
369
416
|
def fetch_multi(*names)
|
417
|
+
raise ArgumentError, "Missing block: `Cache#fetch_multi` requires a block." unless block_given?
|
418
|
+
|
370
419
|
options = names.extract_options!
|
371
420
|
options = merged_options(options)
|
372
|
-
results = read_multi(*names, options)
|
373
421
|
|
374
|
-
names
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
422
|
+
instrument :read_multi, names, options do |payload|
|
423
|
+
read_multi_entries(names, options).tap do |results|
|
424
|
+
payload[:hits] = results.keys
|
425
|
+
payload[:super_operation] = :fetch_multi
|
426
|
+
|
427
|
+
writes = {}
|
428
|
+
|
429
|
+
(names - results.keys).each do |name|
|
430
|
+
results[name] = writes[name] = yield(name)
|
431
|
+
end
|
432
|
+
|
433
|
+
write_multi writes, options
|
379
434
|
end
|
380
435
|
end
|
381
436
|
end
|
@@ -387,8 +442,8 @@ module ActiveSupport
|
|
387
442
|
options = merged_options(options)
|
388
443
|
|
389
444
|
instrument(:write, name, options) do
|
390
|
-
entry = Entry.new(value, options)
|
391
|
-
write_entry(
|
445
|
+
entry = Entry.new(value, options.merge(version: normalize_version(name, options)))
|
446
|
+
write_entry(normalize_key(name, options), entry, options)
|
392
447
|
end
|
393
448
|
end
|
394
449
|
|
@@ -399,7 +454,7 @@ module ActiveSupport
|
|
399
454
|
options = merged_options(options)
|
400
455
|
|
401
456
|
instrument(:delete, name) do
|
402
|
-
delete_entry(
|
457
|
+
delete_entry(normalize_key(name, options), options)
|
403
458
|
end
|
404
459
|
end
|
405
460
|
|
@@ -410,12 +465,12 @@ module ActiveSupport
|
|
410
465
|
options = merged_options(options)
|
411
466
|
|
412
467
|
instrument(:exist?, name) do
|
413
|
-
entry = read_entry(
|
414
|
-
(entry && !entry.expired?) || false
|
468
|
+
entry = read_entry(normalize_key(name, options), options)
|
469
|
+
(entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
|
415
470
|
end
|
416
471
|
end
|
417
472
|
|
418
|
-
#
|
473
|
+
# Deletes all entries with keys matching the pattern.
|
419
474
|
#
|
420
475
|
# Options are passed to the underlying cache implementation.
|
421
476
|
#
|
@@ -424,7 +479,7 @@ module ActiveSupport
|
|
424
479
|
raise NotImplementedError.new("#{self.class.name} does not support delete_matched")
|
425
480
|
end
|
426
481
|
|
427
|
-
#
|
482
|
+
# Increments an integer value in the cache.
|
428
483
|
#
|
429
484
|
# Options are passed to the underlying cache implementation.
|
430
485
|
#
|
@@ -433,7 +488,7 @@ module ActiveSupport
|
|
433
488
|
raise NotImplementedError.new("#{self.class.name} does not support increment")
|
434
489
|
end
|
435
490
|
|
436
|
-
#
|
491
|
+
# Decrements an integer value in the cache.
|
437
492
|
#
|
438
493
|
# Options are passed to the underlying cache implementation.
|
439
494
|
#
|
@@ -442,7 +497,7 @@ module ActiveSupport
|
|
442
497
|
raise NotImplementedError.new("#{self.class.name} does not support decrement")
|
443
498
|
end
|
444
499
|
|
445
|
-
#
|
500
|
+
# Cleanups the cache by removing expired entries.
|
446
501
|
#
|
447
502
|
# Options are passed to the underlying cache implementation.
|
448
503
|
#
|
@@ -451,7 +506,7 @@ module ActiveSupport
|
|
451
506
|
raise NotImplementedError.new("#{self.class.name} does not support cleanup")
|
452
507
|
end
|
453
508
|
|
454
|
-
#
|
509
|
+
# Clears the entire cache. Be careful with this method since it could
|
455
510
|
# affect other processes if shared cache is being used.
|
456
511
|
#
|
457
512
|
# The options hash is passed to the underlying cache implementation.
|
@@ -461,16 +516,16 @@ module ActiveSupport
|
|
461
516
|
raise NotImplementedError.new("#{self.class.name} does not support clear")
|
462
517
|
end
|
463
518
|
|
464
|
-
|
465
|
-
#
|
519
|
+
private
|
520
|
+
# Adds the namespace defined in the options to a pattern designed to
|
466
521
|
# match keys. Implementations that support delete_matched should call
|
467
522
|
# this method to translate a pattern that matches names into one that
|
468
523
|
# matches namespaced keys.
|
469
|
-
def key_matcher(pattern, options)
|
524
|
+
def key_matcher(pattern, options) # :doc:
|
470
525
|
prefix = options[:namespace].is_a?(Proc) ? options[:namespace].call : options[:namespace]
|
471
526
|
if prefix
|
472
527
|
source = pattern.source
|
473
|
-
if source.start_with?(
|
528
|
+
if source.start_with?("^")
|
474
529
|
source = source[1, source.length]
|
475
530
|
else
|
476
531
|
source = ".*#{source[0, source.length]}"
|
@@ -481,27 +536,56 @@ module ActiveSupport
|
|
481
536
|
end
|
482
537
|
end
|
483
538
|
|
484
|
-
#
|
539
|
+
# Reads an entry from the cache implementation. Subclasses must implement
|
485
540
|
# this method.
|
486
|
-
def read_entry(key, options)
|
541
|
+
def read_entry(key, options)
|
487
542
|
raise NotImplementedError.new
|
488
543
|
end
|
489
544
|
|
490
|
-
#
|
545
|
+
# Writes an entry to the cache implementation. Subclasses must implement
|
491
546
|
# this method.
|
492
|
-
def write_entry(key, entry, options)
|
547
|
+
def write_entry(key, entry, options)
|
493
548
|
raise NotImplementedError.new
|
494
549
|
end
|
495
550
|
|
496
|
-
#
|
551
|
+
# Reads multiple entries from the cache implementation. Subclasses MAY
|
497
552
|
# implement this method.
|
498
|
-
def
|
553
|
+
def read_multi_entries(names, options)
|
554
|
+
results = {}
|
555
|
+
names.each do |name|
|
556
|
+
key = normalize_key(name, options)
|
557
|
+
version = normalize_version(name, options)
|
558
|
+
entry = read_entry(key, options)
|
559
|
+
|
560
|
+
if entry
|
561
|
+
if entry.expired?
|
562
|
+
delete_entry(key, options)
|
563
|
+
elsif entry.mismatched?(version)
|
564
|
+
# Skip mismatched versions
|
565
|
+
else
|
566
|
+
results[name] = entry.value
|
567
|
+
end
|
568
|
+
end
|
569
|
+
end
|
570
|
+
results
|
571
|
+
end
|
572
|
+
|
573
|
+
# Writes multiple entries to the cache implementation. Subclasses MAY
|
574
|
+
# implement this method.
|
575
|
+
def write_multi_entries(hash, options)
|
576
|
+
hash.each do |key, entry|
|
577
|
+
write_entry key, entry, options
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
581
|
+
# Deletes an entry from the cache implementation. Subclasses must
|
582
|
+
# implement this method.
|
583
|
+
def delete_entry(key, options)
|
499
584
|
raise NotImplementedError.new
|
500
585
|
end
|
501
586
|
|
502
|
-
|
503
|
-
|
504
|
-
def merged_options(call_options) # :nodoc:
|
587
|
+
# Merges the default options with ones specific to a method call.
|
588
|
+
def merged_options(call_options)
|
505
589
|
if call_options
|
506
590
|
options.merge(call_options)
|
507
591
|
else
|
@@ -509,64 +593,89 @@ module ActiveSupport
|
|
509
593
|
end
|
510
594
|
end
|
511
595
|
|
512
|
-
#
|
596
|
+
# Expands and namespaces the cache key. May be overridden by
|
597
|
+
# cache stores to do additional normalization.
|
598
|
+
def normalize_key(key, options = nil)
|
599
|
+
namespace_key expanded_key(key), options
|
600
|
+
end
|
601
|
+
|
602
|
+
# Prefix the key with a namespace string:
|
603
|
+
#
|
604
|
+
# namespace_key 'foo', namespace: 'cache'
|
605
|
+
# # => 'cache:foo'
|
606
|
+
#
|
607
|
+
# With a namespace block:
|
608
|
+
#
|
609
|
+
# namespace_key 'foo', namespace: -> { 'cache' }
|
610
|
+
# # => 'cache:foo'
|
611
|
+
def namespace_key(key, options = nil)
|
612
|
+
options = merged_options(options)
|
613
|
+
namespace = options[:namespace]
|
614
|
+
|
615
|
+
if namespace.respond_to?(:call)
|
616
|
+
namespace = namespace.call
|
617
|
+
end
|
618
|
+
|
619
|
+
if namespace
|
620
|
+
"#{namespace}:#{key}"
|
621
|
+
else
|
622
|
+
key
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
# Expands key to be a consistent string value. Invokes +cache_key+ if
|
513
627
|
# object responds to +cache_key+. Otherwise, +to_param+ method will be
|
514
628
|
# called. If the key is a Hash, then keys will be sorted alphabetically.
|
515
|
-
def expanded_key(key)
|
629
|
+
def expanded_key(key)
|
516
630
|
return key.cache_key.to_s if key.respond_to?(:cache_key)
|
517
631
|
|
518
632
|
case key
|
519
633
|
when Array
|
520
634
|
if key.size > 1
|
521
|
-
key = key.collect{|element| expanded_key(element)}
|
635
|
+
key = key.collect { |element| expanded_key(element) }
|
522
636
|
else
|
523
637
|
key = key.first
|
524
638
|
end
|
525
639
|
when Hash
|
526
|
-
key = key.sort_by { |k,_| k.to_s }.collect{|k,v| "#{k}=#{v}"}
|
640
|
+
key = key.sort_by { |k, _| k.to_s }.collect { |k, v| "#{k}=#{v}" }
|
527
641
|
end
|
528
642
|
|
529
643
|
key.to_param
|
530
644
|
end
|
531
645
|
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
key
|
539
|
-
key
|
646
|
+
def normalize_version(key, options = nil)
|
647
|
+
(options && options[:version].try(:to_param)) || expanded_version(key)
|
648
|
+
end
|
649
|
+
|
650
|
+
def expanded_version(key)
|
651
|
+
case
|
652
|
+
when key.respond_to?(:cache_version) then key.cache_version.to_param
|
653
|
+
when key.is_a?(Array) then key.map { |element| expanded_version(element) }.compact.to_param
|
654
|
+
when key.respond_to?(:to_a) then expanded_version(key.to_a)
|
655
|
+
end
|
540
656
|
end
|
541
657
|
|
542
658
|
def instrument(operation, key, options = nil)
|
543
|
-
log
|
659
|
+
log { "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}" }
|
544
660
|
|
545
|
-
payload = { :
|
661
|
+
payload = { key: key }
|
546
662
|
payload.merge!(options) if options.is_a?(Hash)
|
547
|
-
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) }
|
663
|
+
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload) { yield(payload) }
|
548
664
|
end
|
549
665
|
|
550
|
-
def log
|
666
|
+
def log
|
551
667
|
return unless logger && logger.debug? && !silence?
|
552
|
-
logger.debug(
|
553
|
-
end
|
554
|
-
|
555
|
-
def find_cached_entry(key, name, options)
|
556
|
-
instrument(:read, name, options) do |payload|
|
557
|
-
payload[:super_operation] = :fetch if payload
|
558
|
-
read_entry(key, options)
|
559
|
-
end
|
668
|
+
logger.debug(yield)
|
560
669
|
end
|
561
670
|
|
562
671
|
def handle_expired_entry(entry, key, options)
|
563
672
|
if entry && entry.expired?
|
564
673
|
race_ttl = options[:race_condition_ttl].to_i
|
565
674
|
if (race_ttl > 0) && (Time.now.to_f - entry.expires_at <= race_ttl)
|
566
|
-
# When an entry has :race_condition_ttl defined, put the stale entry back into the cache
|
567
|
-
# for a brief period while the entry is
|
675
|
+
# When an entry has a positive :race_condition_ttl defined, put the stale entry back into the cache
|
676
|
+
# for a brief period while the entry is being recalculated.
|
568
677
|
entry.expires_at = Time.now + race_ttl
|
569
|
-
write_entry(key, entry, :
|
678
|
+
write_entry(key, entry, expires_in: race_ttl * 2)
|
570
679
|
else
|
571
680
|
delete_entry(key, options)
|
572
681
|
end
|
@@ -576,12 +685,12 @@ module ActiveSupport
|
|
576
685
|
end
|
577
686
|
|
578
687
|
def get_entry_value(entry, name, options)
|
579
|
-
instrument(:fetch_hit, name, options) {
|
688
|
+
instrument(:fetch_hit, name, options) {}
|
580
689
|
entry.value
|
581
690
|
end
|
582
691
|
|
583
692
|
def save_block_result_to_cache(name, options)
|
584
|
-
result = instrument(:generate, name, options) do
|
693
|
+
result = instrument(:generate, name, options) do
|
585
694
|
yield(name)
|
586
695
|
end
|
587
696
|
|
@@ -590,39 +699,40 @@ module ActiveSupport
|
|
590
699
|
end
|
591
700
|
end
|
592
701
|
|
593
|
-
# This class is used to represent cache entries. Cache entries have a value
|
594
|
-
# expiration time. The expiration time is used to support the :race_condition_ttl option
|
595
|
-
# on the cache.
|
702
|
+
# This class is used to represent cache entries. Cache entries have a value, an optional
|
703
|
+
# expiration time, and an optional version. The expiration time is used to support the :race_condition_ttl option
|
704
|
+
# on the cache. The version is used to support the :version option on the cache for rejecting
|
705
|
+
# mismatches.
|
596
706
|
#
|
597
707
|
# Since cache entries in most instances will be serialized, the internals of this class are highly optimized
|
598
708
|
# using short instance variable names that are lazily defined.
|
599
709
|
class Entry # :nodoc:
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
# +:compress+, +:compress_threshold+, and +:expires_in+.
|
604
|
-
def initialize(value, options = {})
|
605
|
-
if should_compress?(value, options)
|
606
|
-
@value = compress(value)
|
607
|
-
@compressed = true
|
608
|
-
else
|
609
|
-
@value = value
|
610
|
-
end
|
710
|
+
attr_reader :version
|
711
|
+
|
712
|
+
DEFAULT_COMPRESS_LIMIT = 1.kilobyte
|
611
713
|
|
714
|
+
# Creates a new cache entry for the specified value. Options supported are
|
715
|
+
# +:compress+, +:compress_threshold+, +:version+ and +:expires_in+.
|
716
|
+
def initialize(value, compress: true, compress_threshold: DEFAULT_COMPRESS_LIMIT, version: nil, expires_in: nil, **)
|
717
|
+
@value = value
|
718
|
+
@version = version
|
612
719
|
@created_at = Time.now.to_f
|
613
|
-
@expires_in =
|
614
|
-
|
720
|
+
@expires_in = expires_in && expires_in.to_f
|
721
|
+
|
722
|
+
compress!(compress_threshold) if compress
|
615
723
|
end
|
616
724
|
|
617
725
|
def value
|
618
|
-
convert_version_4beta1_entry! if defined?(@v)
|
619
726
|
compressed? ? uncompress(@value) : @value
|
620
727
|
end
|
621
728
|
|
622
|
-
|
729
|
+
def mismatched?(version)
|
730
|
+
@version && version && @version != version
|
731
|
+
end
|
732
|
+
|
733
|
+
# Checks if the entry is expired. The +expires_in+ parameter can override
|
623
734
|
# the value set when the entry was created.
|
624
735
|
def expired?
|
625
|
-
convert_version_4beta1_entry! if defined?(@v)
|
626
736
|
@expires_in && @created_at + @expires_in <= Time.now.to_f
|
627
737
|
end
|
628
738
|
|
@@ -641,25 +751,19 @@ module ActiveSupport
|
|
641
751
|
# Returns the size of the cached value. This could be less than
|
642
752
|
# <tt>value.size</tt> if the data is compressed.
|
643
753
|
def size
|
644
|
-
|
645
|
-
|
754
|
+
case value
|
755
|
+
when NilClass
|
756
|
+
0
|
757
|
+
when String
|
758
|
+
@value.bytesize
|
646
759
|
else
|
647
|
-
|
648
|
-
when NilClass
|
649
|
-
0
|
650
|
-
when String
|
651
|
-
@value.bytesize
|
652
|
-
else
|
653
|
-
@s = Marshal.dump(@value).bytesize
|
654
|
-
end
|
760
|
+
@s ||= Marshal.dump(@value).bytesize
|
655
761
|
end
|
656
762
|
end
|
657
763
|
|
658
|
-
#
|
764
|
+
# Duplicates the value in a class. This is used by cache implementations that don't natively
|
659
765
|
# serialize entries to protect against accidental cache modifications.
|
660
766
|
def dup_value!
|
661
|
-
convert_version_4beta1_entry! if defined?(@v)
|
662
|
-
|
663
767
|
if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false)
|
664
768
|
if @value.is_a?(String)
|
665
769
|
@value = @value.dup
|
@@ -670,48 +774,35 @@ module ActiveSupport
|
|
670
774
|
end
|
671
775
|
|
672
776
|
private
|
673
|
-
def
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
777
|
+
def compress!(compress_threshold)
|
778
|
+
case @value
|
779
|
+
when nil, true, false, Numeric
|
780
|
+
uncompressed_size = 0
|
781
|
+
when String
|
782
|
+
uncompressed_size = @value.bytesize
|
783
|
+
else
|
784
|
+
serialized = Marshal.dump(@value)
|
785
|
+
uncompressed_size = serialized.bytesize
|
679
786
|
end
|
680
787
|
|
681
|
-
|
682
|
-
|
788
|
+
if uncompressed_size >= compress_threshold
|
789
|
+
serialized ||= Marshal.dump(@value)
|
790
|
+
compressed = Zlib::Deflate.deflate(serialized)
|
683
791
|
|
684
|
-
|
685
|
-
|
792
|
+
if compressed.bytesize < uncompressed_size
|
793
|
+
@value = compressed
|
794
|
+
@compressed = true
|
795
|
+
end
|
796
|
+
end
|
686
797
|
end
|
687
798
|
|
688
|
-
def
|
689
|
-
|
799
|
+
def compressed?
|
800
|
+
defined?(@compressed)
|
690
801
|
end
|
691
802
|
|
692
803
|
def uncompress(value)
|
693
804
|
Marshal.load(Zlib::Inflate.inflate(value))
|
694
805
|
end
|
695
|
-
|
696
|
-
# The internals of this method changed between Rails 3.x and 4.0. This method provides the glue
|
697
|
-
# to ensure that cache entries created under the old version still work with the new class definition.
|
698
|
-
def convert_version_4beta1_entry!
|
699
|
-
if defined?(@v)
|
700
|
-
@value = @v
|
701
|
-
remove_instance_variable(:@v)
|
702
|
-
end
|
703
|
-
|
704
|
-
if defined?(@c)
|
705
|
-
@compressed = @c
|
706
|
-
remove_instance_variable(:@c)
|
707
|
-
end
|
708
|
-
|
709
|
-
if defined?(@x) && @x
|
710
|
-
@created_at ||= Time.now.to_f
|
711
|
-
@expires_in = @x - @created_at
|
712
|
-
remove_instance_variable(:@x)
|
713
|
-
end
|
714
|
-
end
|
715
806
|
end
|
716
807
|
end
|
717
808
|
end
|