activesupport 5.1.7 → 7.0.4.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +259 -585
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -5
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +2 -0
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +33 -5
- data/lib/active_support/benchmarkable.rb +5 -3
- data/lib/active_support/builder.rb +2 -0
- data/lib/active_support/cache/file_store.rb +50 -43
- data/lib/active_support/cache/mem_cache_store.rb +194 -67
- data/lib/active_support/cache/memory_store.rb +70 -34
- data/lib/active_support/cache/null_store.rb +18 -3
- data/lib/active_support/cache/redis_cache_store.rb +474 -0
- data/lib/active_support/cache/strategy/local_cache.rb +73 -50
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
- data/lib/active_support/cache.rb +556 -220
- data/lib/active_support/callbacks.rb +264 -159
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +81 -8
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +16 -0
- data/lib/active_support/concurrency/share_lock.rb +4 -3
- data/lib/active_support/configurable.rb +17 -16
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +18 -8
- data/lib/active_support/core_ext/array/conversions.rb +20 -17
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +8 -6
- data/lib/active_support/core_ext/array/inquiry.rb +4 -2
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +4 -1
- data/lib/active_support/core_ext/benchmark.rb +4 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +3 -1
- data/lib/active_support/core_ext/big_decimal.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +50 -47
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/class/subclasses.rb +10 -24
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/date/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date/blank.rb +3 -1
- data/lib/active_support/core_ext/date/calculations.rb +17 -14
- data/lib/active_support/core_ext/date/conversions.rb +24 -22
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date/zones.rb +2 -0
- data/lib/active_support/core_ext/date.rb +3 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +65 -41
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date_time/blank.rb +3 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
- data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +15 -14
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +3 -0
- data/lib/active_support/core_ext/digest/uuid.rb +42 -14
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +244 -72
- data/lib/active_support/core_ext/file/atomic.rb +6 -2
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/hash/conversions.rb +7 -6
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
- data/lib/active_support/core_ext/hash/keys.rb +4 -31
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +3 -2
- data/lib/active_support/core_ext/integer/inflections.rb +2 -0
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +7 -14
- data/lib/active_support/core_ext/integer.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +6 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +3 -1
- data/lib/active_support/core_ext/kernel.rb +2 -1
- data/lib/active_support/core_ext/load_error.rb +3 -8
- data/lib/active_support/core_ext/module/aliasing.rb +2 -0
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -56
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +36 -27
- data/lib/active_support/core_ext/module/concerning.rb +15 -10
- data/lib/active_support/core_ext/module/delegation.rb +97 -58
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +18 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +3 -1
- data/lib/active_support/core_ext/name_error.rb +30 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +134 -129
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric/time.rb +7 -15
- data/lib/active_support/core_ext/numeric.rb +3 -1
- data/lib/active_support/core_ext/object/acts_like.rb +41 -6
- data/lib/active_support/core_ext/object/blank.rb +15 -5
- data/lib/active_support/core_ext/object/conversions.rb +2 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
- data/lib/active_support/core_ext/object/duplicable.rb +16 -110
- data/lib/active_support/core_ext/object/inclusion.rb +2 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +51 -26
- data/lib/active_support/core_ext/object/to_param.rb +2 -0
- data/lib/active_support/core_ext/object/to_query.rb +4 -2
- data/lib/active_support/core_ext/object/try.rb +26 -14
- data/lib/active_support/core_ext/object/with_options.rb +24 -3
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +6 -3
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
- data/lib/active_support/core_ext/range/overlaps.rb +3 -1
- data/lib/active_support/core_ext/range.rb +4 -1
- data/lib/active_support/core_ext/regexp.rb +10 -5
- data/lib/active_support/core_ext/securerandom.rb +25 -3
- data/lib/active_support/core_ext/string/access.rb +7 -16
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +5 -2
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +44 -1
- data/lib/active_support/core_ext/string/indent.rb +2 -0
- data/lib/active_support/core_ext/string/inflections.rb +69 -16
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +9 -4
- data/lib/active_support/core_ext/string/output_safety.rb +135 -27
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +2 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/time/calculations.rb +81 -24
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +17 -12
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +12 -25
- data/lib/active_support/core_ext/time.rb +3 -0
- data/lib/active_support/core_ext/uri.rb +4 -23
- data/lib/active_support/core_ext.rb +4 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +226 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +12 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +59 -715
- data/lib/active_support/deprecation/behaviors.rb +48 -13
- data/lib/active_support/deprecation/constant_accessor.rb +4 -2
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +2 -1
- data/lib/active_support/deprecation/method_wrappers.rb +29 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +34 -8
- data/lib/active_support/deprecation/reporting.rb +54 -9
- data/lib/active_support/deprecation.rb +10 -3
- data/lib/active_support/descendants_tracker.rb +192 -34
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +9 -9
- data/lib/active_support/duration/iso8601_serializer.rb +29 -15
- data/lib/active_support/duration.rb +158 -72
- data/lib/active_support/encrypted_configuration.rb +56 -0
- data/lib/active_support/encrypted_file.rb +129 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +87 -122
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +46 -21
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/executor.rb +2 -0
- data/lib/active_support/file_update_checker.rb +2 -1
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +7 -5
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +126 -42
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +5 -1
- data/lib/active_support/i18n_railtie.rb +19 -14
- data/lib/active_support/inflections.rb +2 -0
- data/lib/active_support/inflector/inflections.rb +41 -14
- data/lib/active_support/inflector/methods.rb +73 -87
- data/lib/active_support/inflector/transliterate.rb +56 -18
- data/lib/active_support/inflector.rb +2 -0
- data/lib/active_support/isolated_execution_state.rb +72 -0
- data/lib/active_support/json/decoding.rb +27 -26
- data/lib/active_support/json/encoding.rb +16 -6
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/key_generator.rb +25 -38
- data/lib/active_support/lazy_load_hooks.rb +35 -6
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +8 -4
- data/lib/active_support/log_subscriber/test_helper.rb +4 -2
- data/lib/active_support/log_subscriber.rb +54 -13
- data/lib/active_support/logger.rb +4 -17
- data/lib/active_support/logger_silence.rb +13 -20
- data/lib/active_support/logger_thread_safe_level.rb +48 -10
- data/lib/active_support/message_encryptor.rb +111 -37
- data/lib/active_support/message_verifier.rb +124 -21
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +19 -76
- data/lib/active_support/multibyte/unicode.rb +9 -331
- data/lib/active_support/multibyte.rb +3 -1
- data/lib/active_support/notifications/fanout.rb +165 -37
- data/lib/active_support/notifications/instrumenter.rb +92 -11
- data/lib/active_support/notifications.rb +96 -30
- data/lib/active_support/number_helper/number_converter.rb +8 -9
- data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -12
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +7 -4
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
- data/lib/active_support/number_helper/rounding_helper.rb +16 -34
- data/lib/active_support/number_helper.rb +38 -12
- data/lib/active_support/option_merger.rb +19 -6
- data/lib/active_support/ordered_hash.rb +4 -2
- data/lib/active_support/ordered_options.rb +18 -6
- data/lib/active_support/parameter_filter.rb +138 -0
- data/lib/active_support/per_thread_registry.rb +8 -1
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +3 -10
- data/lib/active_support/railtie.rb +112 -11
- data/lib/active_support/reloader.rb +12 -11
- data/lib/active_support/rescuable.rb +19 -18
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +4 -3
- data/lib/active_support/subscriber.rb +81 -42
- data/lib/active_support/tagged_logging.rb +45 -9
- data/lib/active_support/test_case.rb +86 -2
- data/lib/active_support/testing/assertions.rb +89 -21
- data/lib/active_support/testing/autorun.rb +2 -0
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/testing/declarative.rb +2 -0
- data/lib/active_support/testing/deprecation.rb +54 -2
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +6 -4
- data/lib/active_support/testing/method_call_assertions.rb +34 -5
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +55 -0
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -7
- data/lib/active_support/testing/stream.rb +6 -7
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +91 -15
- data/lib/active_support/time.rb +2 -0
- data/lib/active_support/time_with_zone.rb +168 -56
- data/lib/active_support/values/time_zone.rb +85 -37
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +6 -5
- data/lib/active_support/xml_mini/libxml.rb +9 -7
- data/lib/active_support/xml_mini/libxmlsax.rb +7 -5
- data/lib/active_support/xml_mini/nokogiri.rb +8 -6
- data/lib/active_support/xml_mini/nokogirisax.rb +6 -4
- data/lib/active_support/xml_mini/rexml.rb +13 -4
- data/lib/active_support/xml_mini.rb +10 -15
- data/lib/active_support.rb +30 -9
- metadata +76 -35
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/marshal.rb +0 -22
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require "dalli"
|
3
5
|
rescue LoadError => e
|
@@ -5,14 +7,14 @@ rescue LoadError => e
|
|
5
7
|
raise e
|
6
8
|
end
|
7
9
|
|
8
|
-
require "
|
9
|
-
require "active_support/core_ext/
|
10
|
+
require "delegate"
|
11
|
+
require "active_support/core_ext/enumerable"
|
10
12
|
require "active_support/core_ext/array/extract_options"
|
11
13
|
|
12
14
|
module ActiveSupport
|
13
15
|
module Cache
|
14
16
|
# A cache store implementation which stores data in Memcached:
|
15
|
-
#
|
17
|
+
# https://memcached.org
|
16
18
|
#
|
17
19
|
# This is currently the most popular cache store for production websites.
|
18
20
|
#
|
@@ -24,45 +26,76 @@ module ActiveSupport
|
|
24
26
|
# MemCacheStore implements the Strategy::LocalCache strategy which implements
|
25
27
|
# an in-memory cache inside of a block.
|
26
28
|
class MemCacheStore < Store
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
# Advertise cache versioning support.
|
30
|
+
def self.supports_cache_versioning?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
prepend Strategy::LocalCache
|
35
|
+
|
36
|
+
module DupLocalCache
|
37
|
+
class DupLocalStore < DelegateClass(Strategy::LocalCache::LocalStore)
|
38
|
+
def write_entry(_key, entry)
|
39
|
+
if entry.is_a?(Entry)
|
40
|
+
entry.dup_value!
|
41
|
+
end
|
42
|
+
super
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch_entry(key)
|
46
|
+
entry = super do
|
47
|
+
new_entry = yield
|
48
|
+
if entry.is_a?(Entry)
|
49
|
+
new_entry.dup_value!
|
50
|
+
end
|
51
|
+
new_entry
|
52
|
+
end
|
53
|
+
entry = entry.dup
|
54
|
+
|
55
|
+
if entry.is_a?(Entry)
|
56
|
+
entry.dup_value!
|
34
57
|
end
|
58
|
+
|
35
59
|
entry
|
36
60
|
end
|
61
|
+
end
|
37
62
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
63
|
+
private
|
64
|
+
def local_cache
|
65
|
+
if ActiveSupport::Cache.format_version == 6.1
|
66
|
+
if local_cache = super
|
67
|
+
DupLocalStore.new(local_cache)
|
68
|
+
end
|
43
69
|
else
|
44
70
|
super
|
45
71
|
end
|
46
72
|
end
|
47
73
|
end
|
48
|
-
|
49
|
-
prepend Strategy::LocalCache
|
50
|
-
prepend LocalCacheWithRaw
|
74
|
+
prepend DupLocalCache
|
51
75
|
|
52
76
|
ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
|
53
77
|
|
54
78
|
# Creates a new Dalli::Client instance with specified addresses and options.
|
55
|
-
#
|
79
|
+
# If no addresses are provided, we give nil to Dalli::Client, so it uses its fallbacks:
|
80
|
+
# - ENV["MEMCACHE_SERVERS"] (if defined)
|
81
|
+
# - "127.0.0.1:11211" (otherwise)
|
56
82
|
#
|
57
83
|
# ActiveSupport::Cache::MemCacheStore.build_mem_cache
|
58
|
-
# # => #<Dalli::Client:0x007f98a47d2028 @servers=["
|
84
|
+
# # => #<Dalli::Client:0x007f98a47d2028 @servers=["127.0.0.1:11211"], @options={}, @ring=nil>
|
59
85
|
# ActiveSupport::Cache::MemCacheStore.build_mem_cache('localhost:10290')
|
60
86
|
# # => #<Dalli::Client:0x007f98a47b3a60 @servers=["localhost:10290"], @options={}, @ring=nil>
|
61
87
|
def self.build_mem_cache(*addresses) # :nodoc:
|
62
88
|
addresses = addresses.flatten
|
63
89
|
options = addresses.extract_options!
|
64
|
-
addresses =
|
65
|
-
|
90
|
+
addresses = nil if addresses.compact.empty?
|
91
|
+
pool_options = retrieve_pool_options(options)
|
92
|
+
|
93
|
+
if pool_options.empty?
|
94
|
+
Dalli::Client.new(addresses, options)
|
95
|
+
else
|
96
|
+
ensure_connection_pool_added!
|
97
|
+
ConnectionPool.new(pool_options) { Dalli::Client.new(addresses, options.merge(threadsafe: false)) }
|
98
|
+
end
|
66
99
|
end
|
67
100
|
|
68
101
|
# Creates a new MemCacheStore object, with the given memcached server
|
@@ -71,11 +104,14 @@ module ActiveSupport
|
|
71
104
|
#
|
72
105
|
# ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
|
73
106
|
#
|
74
|
-
# If no addresses are
|
75
|
-
#
|
107
|
+
# If no addresses are provided, but <tt>ENV['MEMCACHE_SERVERS']</tt> is defined, it will be used instead. Otherwise,
|
108
|
+
# MemCacheStore will connect to localhost:11211 (the default memcached port).
|
76
109
|
def initialize(*addresses)
|
77
110
|
addresses = addresses.flatten
|
78
111
|
options = addresses.extract_options!
|
112
|
+
if options.key?(:cache_nils)
|
113
|
+
options[:skip_nil] = !options.delete(:cache_nils)
|
114
|
+
end
|
79
115
|
super(options)
|
80
116
|
|
81
117
|
unless [String, Dalli::Client, NilClass].include?(addresses.first.class)
|
@@ -85,49 +121,51 @@ module ActiveSupport
|
|
85
121
|
@data = addresses.first
|
86
122
|
else
|
87
123
|
mem_cache_options = options.dup
|
88
|
-
|
124
|
+
# The value "compress: false" prevents duplicate compression within Dalli.
|
125
|
+
mem_cache_options[:compress] = false
|
126
|
+
(UNIVERSAL_OPTIONS - %i(compress)).each { |name| mem_cache_options.delete(name) }
|
89
127
|
@data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
|
90
128
|
end
|
91
129
|
end
|
92
130
|
|
93
|
-
|
94
|
-
#
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
131
|
+
##
|
132
|
+
# :method: write
|
133
|
+
# :call-seq: write(name, value, options = nil)
|
134
|
+
#
|
135
|
+
# Behaves the same as ActiveSupport::Cache::Store#write, but supports
|
136
|
+
# additional options specific to memcached.
|
137
|
+
#
|
138
|
+
# ==== Additional Options
|
139
|
+
#
|
140
|
+
# * <tt>raw: true</tt> - Sends the value directly to the server as raw
|
141
|
+
# bytes. The value must be a string or number. You can use memcached
|
142
|
+
# direct operations like +increment+ and +decrement+ only on raw values.
|
143
|
+
#
|
144
|
+
# * <tt>unless_exist: true</tt> - Prevents overwriting an existing cache
|
145
|
+
# entry.
|
108
146
|
|
109
147
|
# Increment a cached value. This method uses the memcached incr atomic
|
110
|
-
# operator and can only be used on values written with the
|
111
|
-
# Calling it on a value not stored with
|
148
|
+
# operator and can only be used on values written with the +:raw+ option.
|
149
|
+
# Calling it on a value not stored with +:raw+ will initialize that value
|
112
150
|
# to zero.
|
113
151
|
def increment(name, amount = 1, options = nil)
|
114
152
|
options = merged_options(options)
|
115
153
|
instrument(:increment, name, amount: amount) do
|
116
154
|
rescue_error_with nil do
|
117
|
-
@data.incr(normalize_key(name, options), amount)
|
155
|
+
@data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in]) }
|
118
156
|
end
|
119
157
|
end
|
120
158
|
end
|
121
159
|
|
122
160
|
# Decrement a cached value. This method uses the memcached decr atomic
|
123
|
-
# operator and can only be used on values written with the
|
124
|
-
# Calling it on a value not stored with
|
161
|
+
# operator and can only be used on values written with the +:raw+ option.
|
162
|
+
# Calling it on a value not stored with +:raw+ will initialize that value
|
125
163
|
# to zero.
|
126
164
|
def decrement(name, amount = 1, options = nil)
|
127
165
|
options = merged_options(options)
|
128
166
|
instrument(:decrement, name, amount: amount) do
|
129
167
|
rescue_error_with nil do
|
130
|
-
@data.decr(normalize_key(name, options), amount)
|
168
|
+
@data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in]) }
|
131
169
|
end
|
132
170
|
end
|
133
171
|
end
|
@@ -135,61 +173,150 @@ module ActiveSupport
|
|
135
173
|
# Clear the entire cache on all memcached servers. This method should
|
136
174
|
# be used with care when shared cache is being used.
|
137
175
|
def clear(options = nil)
|
138
|
-
rescue_error_with(nil) { @data.flush_all }
|
176
|
+
rescue_error_with(nil) { @data.with { |c| c.flush_all } }
|
139
177
|
end
|
140
178
|
|
141
179
|
# Get the statistics from the memcached servers.
|
142
180
|
def stats
|
143
|
-
@data.stats
|
181
|
+
@data.with { |c| c.stats }
|
144
182
|
end
|
145
183
|
|
146
184
|
private
|
185
|
+
module Coders # :nodoc:
|
186
|
+
class << self
|
187
|
+
def [](version)
|
188
|
+
case version
|
189
|
+
when 6.1
|
190
|
+
Rails61Coder
|
191
|
+
when 7.0
|
192
|
+
Rails70Coder
|
193
|
+
else
|
194
|
+
raise ArgumentError, "Unknown ActiveSupport::Cache.format_version #{Cache.format_version.inspect}"
|
195
|
+
end
|
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
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def default_coder
|
230
|
+
Coders[Cache.format_version]
|
231
|
+
end
|
232
|
+
|
147
233
|
# Read an entry from the cache.
|
148
|
-
def read_entry(key, options)
|
149
|
-
|
234
|
+
def read_entry(key, **options)
|
235
|
+
deserialize_entry(read_serialized_entry(key, **options), **options)
|
236
|
+
end
|
237
|
+
|
238
|
+
def read_serialized_entry(key, **options)
|
239
|
+
rescue_error_with(nil) do
|
240
|
+
@data.with { |c| c.get(key, options) }
|
241
|
+
end
|
150
242
|
end
|
151
243
|
|
152
244
|
# Write an entry to the cache.
|
153
|
-
def write_entry(key, entry, options)
|
154
|
-
|
155
|
-
|
245
|
+
def write_entry(key, entry, **options)
|
246
|
+
write_serialized_entry(key, serialize_entry(entry, **options), **options)
|
247
|
+
end
|
248
|
+
|
249
|
+
def write_serialized_entry(key, payload, **options)
|
250
|
+
method = options[:unless_exist] ? :add : :set
|
156
251
|
expires_in = options[:expires_in].to_i
|
157
|
-
if expires_in > 0 && !options[:raw]
|
252
|
+
if options[:race_condition_ttl] && expires_in > 0 && !options[:raw]
|
158
253
|
# Set the memcache expire a few minutes in the future to support race condition ttls on read
|
159
254
|
expires_in += 5.minutes
|
160
255
|
end
|
161
256
|
rescue_error_with false do
|
162
|
-
|
257
|
+
# Don't pass compress option to Dalli since we are already dealing with compression.
|
258
|
+
options.delete(:compress)
|
259
|
+
@data.with { |c| c.send(method, key, payload, expires_in, **options) }
|
163
260
|
end
|
164
261
|
end
|
165
262
|
|
263
|
+
# Reads multiple entries from the cache implementation.
|
264
|
+
def read_multi_entries(names, **options)
|
265
|
+
keys_to_names = names.index_by { |name| normalize_key(name, options) }
|
266
|
+
|
267
|
+
raw_values = @data.with { |c| c.get_multi(keys_to_names.keys) }
|
268
|
+
values = {}
|
269
|
+
|
270
|
+
raw_values.each do |key, value|
|
271
|
+
entry = deserialize_entry(value, raw: options[:raw])
|
272
|
+
|
273
|
+
unless entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
|
274
|
+
values[keys_to_names[key]] = entry.value
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
values
|
279
|
+
end
|
280
|
+
|
166
281
|
# Delete an entry from the cache.
|
167
|
-
def delete_entry(key, options)
|
168
|
-
rescue_error_with(false) { @data.delete(key) }
|
282
|
+
def delete_entry(key, **options)
|
283
|
+
rescue_error_with(false) { @data.with { |c| c.delete(key) } }
|
284
|
+
end
|
285
|
+
|
286
|
+
def serialize_entry(entry, raw: false, **options)
|
287
|
+
if raw
|
288
|
+
entry.value.to_s
|
289
|
+
else
|
290
|
+
super(entry, raw: raw, **options)
|
291
|
+
end
|
169
292
|
end
|
170
293
|
|
171
294
|
# Memcache keys are binaries. So we need to force their encoding to binary
|
172
295
|
# before applying the regular expression to ensure we are escaping all
|
173
296
|
# characters properly.
|
174
297
|
def normalize_key(key, options)
|
175
|
-
key = super
|
176
|
-
|
177
|
-
|
178
|
-
|
298
|
+
key = super
|
299
|
+
if key
|
300
|
+
key = key.dup.force_encoding(Encoding::ASCII_8BIT)
|
301
|
+
key = key.gsub(ESCAPE_KEY_CHARS) { |match| "%#{match.getbyte(0).to_s(16).upcase}" }
|
302
|
+
key = "#{key[0, 212]}:hash:#{ActiveSupport::Digest.hexdigest(key)}" if key.size > 250
|
303
|
+
end
|
179
304
|
key
|
180
305
|
end
|
181
306
|
|
182
|
-
def deserialize_entry(
|
183
|
-
if
|
184
|
-
|
185
|
-
|
307
|
+
def deserialize_entry(payload, raw: false, **)
|
308
|
+
if payload && raw
|
309
|
+
Entry.new(payload)
|
310
|
+
else
|
311
|
+
super(payload)
|
186
312
|
end
|
187
313
|
end
|
188
314
|
|
189
315
|
def rescue_error_with(fallback)
|
190
316
|
yield
|
191
|
-
rescue Dalli::DalliError =>
|
192
|
-
|
317
|
+
rescue Dalli::DalliError => error
|
318
|
+
ActiveSupport.error_reporter&.report(error, handled: true, severity: :warning)
|
319
|
+
logger.error("DalliError (#{error}): #{error.message}") if logger
|
193
320
|
fallback
|
194
321
|
end
|
195
322
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "monitor"
|
2
4
|
|
3
5
|
module ActiveSupport
|
@@ -9,18 +11,46 @@ module ActiveSupport
|
|
9
11
|
# to share cache data with each other and this may not be the most
|
10
12
|
# appropriate cache in that scenario.
|
11
13
|
#
|
12
|
-
# This cache has a bounded size specified by the
|
14
|
+
# This cache has a bounded size specified by the +:size+ options to the
|
13
15
|
# initializer (default is 32Mb). When the cache exceeds the allotted size,
|
14
16
|
# a cleanup will occur which tries to prune the cache down to three quarters
|
15
17
|
# of the maximum size by removing the least recently used entries.
|
16
18
|
#
|
19
|
+
# Unlike other Cache store implementations, MemoryStore does not compress
|
20
|
+
# values by default. MemoryStore does not benefit from compression as much
|
21
|
+
# as other Store implementations, as it does not send data over a network.
|
22
|
+
# However, when compression is enabled, it still pays the full cost of
|
23
|
+
# compression in terms of cpu use.
|
24
|
+
#
|
17
25
|
# MemoryStore is thread-safe.
|
18
26
|
class MemoryStore < Store
|
27
|
+
module DupCoder # :nodoc:
|
28
|
+
extend self
|
29
|
+
|
30
|
+
def dump(entry)
|
31
|
+
entry.dup_value! unless entry.compressed?
|
32
|
+
entry
|
33
|
+
end
|
34
|
+
|
35
|
+
def dump_compressed(entry, threshold)
|
36
|
+
entry = entry.compressed(threshold)
|
37
|
+
entry.dup_value! unless entry.compressed?
|
38
|
+
entry
|
39
|
+
end
|
40
|
+
|
41
|
+
def load(entry)
|
42
|
+
entry = entry.dup
|
43
|
+
entry.dup_value!
|
44
|
+
entry
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
19
48
|
def initialize(options = nil)
|
20
49
|
options ||= {}
|
50
|
+
# Disable compression by default.
|
51
|
+
options[:compress] ||= false
|
21
52
|
super(options)
|
22
53
|
@data = {}
|
23
|
-
@key_access = {}
|
24
54
|
@max_size = options[:size] || 32.megabytes
|
25
55
|
@max_prune_time = options[:max_prune_time] || 2
|
26
56
|
@cache_size = 0
|
@@ -28,11 +58,15 @@ module ActiveSupport
|
|
28
58
|
@pruning = false
|
29
59
|
end
|
30
60
|
|
61
|
+
# Advertise cache versioning support.
|
62
|
+
def self.supports_cache_versioning?
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
31
66
|
# Delete all data stored in a given cache store.
|
32
67
|
def clear(options = nil)
|
33
68
|
synchronize do
|
34
69
|
@data.clear
|
35
|
-
@key_access.clear
|
36
70
|
@cache_size = 0
|
37
71
|
end
|
38
72
|
end
|
@@ -44,7 +78,7 @@ module ActiveSupport
|
|
44
78
|
keys = synchronize { @data.keys }
|
45
79
|
keys.each do |key|
|
46
80
|
entry = @data[key]
|
47
|
-
delete_entry(key, options) if entry && entry.expired?
|
81
|
+
delete_entry(key, **options) if entry && entry.expired?
|
48
82
|
end
|
49
83
|
end
|
50
84
|
end
|
@@ -55,13 +89,13 @@ module ActiveSupport
|
|
55
89
|
return if pruning?
|
56
90
|
@pruning = true
|
57
91
|
begin
|
58
|
-
start_time =
|
92
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
59
93
|
cleanup
|
60
94
|
instrument(:prune, target_size, from: @cache_size) do
|
61
|
-
keys = synchronize { @
|
95
|
+
keys = synchronize { @data.keys }
|
62
96
|
keys.each do |key|
|
63
|
-
delete_entry(key, options)
|
64
|
-
return if @cache_size <= target_size || (max_time &&
|
97
|
+
delete_entry(key, **options)
|
98
|
+
return if @cache_size <= target_size || (max_time && Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time > max_time)
|
65
99
|
end
|
66
100
|
end
|
67
101
|
ensure
|
@@ -91,13 +125,13 @@ module ActiveSupport
|
|
91
125
|
matcher = key_matcher(matcher, options)
|
92
126
|
keys = synchronize { @data.keys }
|
93
127
|
keys.each do |key|
|
94
|
-
delete_entry(key, options) if key.match(matcher)
|
128
|
+
delete_entry(key, **options) if key.match(matcher)
|
95
129
|
end
|
96
130
|
end
|
97
131
|
end
|
98
132
|
|
99
133
|
def inspect # :nodoc:
|
100
|
-
"
|
134
|
+
"#<#{self.class.name} entries=#{@data.size}, size=#{@cache_size}, options=#{@options.inspect}>"
|
101
135
|
end
|
102
136
|
|
103
137
|
# Synchronize calls to the cache. This should be called wherever the underlying cache implementation
|
@@ -107,54 +141,56 @@ module ActiveSupport
|
|
107
141
|
end
|
108
142
|
|
109
143
|
private
|
110
|
-
|
111
144
|
PER_ENTRY_OVERHEAD = 240
|
112
145
|
|
113
|
-
def
|
114
|
-
|
146
|
+
def default_coder
|
147
|
+
DupCoder
|
115
148
|
end
|
116
149
|
|
117
|
-
def
|
118
|
-
|
150
|
+
def cached_size(key, payload)
|
151
|
+
key.to_s.bytesize + payload.bytesize + PER_ENTRY_OVERHEAD
|
152
|
+
end
|
153
|
+
|
154
|
+
def read_entry(key, **options)
|
155
|
+
entry = nil
|
119
156
|
synchronize do
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
157
|
+
payload = @data.delete(key)
|
158
|
+
if payload
|
159
|
+
@data[key] = payload
|
160
|
+
entry = deserialize_entry(payload)
|
124
161
|
end
|
125
162
|
end
|
126
163
|
entry
|
127
164
|
end
|
128
165
|
|
129
|
-
def write_entry(key, entry, options)
|
130
|
-
entry
|
166
|
+
def write_entry(key, entry, **options)
|
167
|
+
payload = serialize_entry(entry, **options)
|
131
168
|
synchronize do
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
169
|
+
return false if options[:unless_exist] && @data.key?(key)
|
170
|
+
|
171
|
+
old_payload = @data[key]
|
172
|
+
if old_payload
|
173
|
+
@cache_size -= (old_payload.bytesize - payload.bytesize)
|
136
174
|
else
|
137
|
-
@cache_size += cached_size(key,
|
175
|
+
@cache_size += cached_size(key, payload)
|
138
176
|
end
|
139
|
-
@
|
140
|
-
@data[key] = entry
|
177
|
+
@data[key] = payload
|
141
178
|
prune(@max_size * 0.75, @max_prune_time) if @cache_size > @max_size
|
142
179
|
true
|
143
180
|
end
|
144
181
|
end
|
145
182
|
|
146
|
-
def delete_entry(key, options)
|
183
|
+
def delete_entry(key, **options)
|
147
184
|
synchronize do
|
148
|
-
@
|
149
|
-
|
150
|
-
|
151
|
-
!!entry
|
185
|
+
payload = @data.delete(key)
|
186
|
+
@cache_size -= cached_size(key, payload) if payload
|
187
|
+
!!payload
|
152
188
|
end
|
153
189
|
end
|
154
190
|
|
155
191
|
def modify_value(name, amount, options)
|
192
|
+
options = merged_options(options)
|
156
193
|
synchronize do
|
157
|
-
options = merged_options(options)
|
158
194
|
if num = read(name, options)
|
159
195
|
num = num.to_i + amount
|
160
196
|
write(name, num, options)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
module Cache
|
3
5
|
# A cache store implementation which doesn't actually store anything. Useful in
|
@@ -10,6 +12,11 @@ module ActiveSupport
|
|
10
12
|
class NullStore < Store
|
11
13
|
prepend Strategy::LocalCache
|
12
14
|
|
15
|
+
# Advertise cache versioning support.
|
16
|
+
def self.supports_cache_versioning?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
13
20
|
def clear(options = nil)
|
14
21
|
end
|
15
22
|
|
@@ -26,14 +33,22 @@ module ActiveSupport
|
|
26
33
|
end
|
27
34
|
|
28
35
|
private
|
29
|
-
def read_entry(key,
|
36
|
+
def read_entry(key, **s)
|
37
|
+
deserialize_entry(read_serialized_entry(key))
|
38
|
+
end
|
39
|
+
|
40
|
+
def read_serialized_entry(_key, **)
|
41
|
+
end
|
42
|
+
|
43
|
+
def write_entry(key, entry, **)
|
44
|
+
write_serialized_entry(key, serialize_entry(entry))
|
30
45
|
end
|
31
46
|
|
32
|
-
def
|
47
|
+
def write_serialized_entry(_key, _payload, **)
|
33
48
|
true
|
34
49
|
end
|
35
50
|
|
36
|
-
def delete_entry(key, options)
|
51
|
+
def delete_entry(key, **options)
|
37
52
|
false
|
38
53
|
end
|
39
54
|
end
|