activesupport 7.0.8.7 → 7.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +722 -314
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +2 -0
- data/lib/active_support/backtrace_cleaner.rb +25 -5
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +128 -0
- data/lib/active_support/cache/file_store.rb +36 -9
- data/lib/active_support/cache/mem_cache_store.rb +84 -68
- data/lib/active_support/cache/memory_store.rb +76 -24
- data/lib/active_support/cache/null_store.rb +6 -0
- data/lib/active_support/cache/redis_cache_store.rb +126 -131
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +20 -8
- data/lib/active_support/cache.rb +304 -246
- data/lib/active_support/callbacks.rb +38 -18
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +10 -0
- data/lib/active_support/core_ext/array/conversions.rb +2 -1
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/class/subclasses.rb +13 -10
- data/lib/active_support/core_ext/date/conversions.rb +1 -0
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +1 -10
- data/lib/active_support/core_ext/enumerable.rb +3 -75
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
- data/lib/active_support/core_ext/module/delegation.rb +40 -11
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/duplicable.rb +15 -24
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +10 -2
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +3 -3
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +28 -7
- data/lib/active_support/core_ext/range/{overlaps.rb → overlap.rb} +5 -3
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +24 -12
- data/lib/active_support/core_ext/string/filters.rb +20 -14
- data/lib/active_support/core_ext/string/inflections.rb +16 -5
- data/lib/active_support/core_ext/string/output_safety.rb +38 -174
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +18 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -2
- data/lib/active_support/core_ext/time/zones.rb +4 -4
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/current_attributes.rb +15 -6
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/deprecation/behaviors.rb +53 -32
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +3 -5
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
- data/lib/active_support/deprecation/reporting.rb +35 -21
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +104 -132
- data/lib/active_support/duration/iso8601_serializer.rb +0 -2
- data/lib/active_support/duration.rb +2 -1
- data/lib/active_support/encrypted_configuration.rb +30 -9
- data/lib/active_support/encrypted_file.rb +8 -3
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +121 -35
- data/lib/active_support/execution_wrapper.rb +4 -4
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +10 -2
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +35 -17
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +22 -10
- data/lib/active_support/inflector/transliterate.rb +3 -1
- data/lib/active_support/isolated_execution_state.rb +26 -22
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +25 -43
- data/lib/active_support/key_generator.rb +9 -1
- data/lib/active_support/lazy_load_hooks.rb +6 -4
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +78 -33
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_thread_safe_level.rb +9 -21
- data/lib/active_support/message_encryptor.rb +197 -53
- data/lib/active_support/message_encryptors.rb +140 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +212 -93
- data/lib/active_support/message_verifiers.rb +134 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +111 -45
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +239 -81
- data/lib/active_support/notifications/instrumenter.rb +71 -14
- data/lib/active_support/notifications.rb +1 -1
- data/lib/active_support/number_helper/number_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +14 -0
- data/lib/active_support/parameter_filter.rb +84 -69
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +33 -21
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +2 -0
- data/lib/active_support/secure_compare_rotator.rb +16 -9
- data/lib/active_support/string_inquirer.rb +3 -1
- data/lib/active_support/subscriber.rb +9 -27
- data/lib/active_support/syntax_error_proxy.rb +49 -0
- data/lib/active_support/tagged_logging.rb +60 -24
- data/lib/active_support/test_case.rb +153 -6
- data/lib/active_support/testing/assertions.rb +25 -9
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +25 -25
- data/lib/active_support/testing/error_reporter_assertions.rb +108 -0
- data/lib/active_support/testing/isolation.rb +1 -1
- data/lib/active_support/testing/method_call_assertions.rb +21 -8
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +38 -0
- data/lib/active_support/testing/time_helpers.rb +32 -14
- data/lib/active_support/time_with_zone.rb +4 -14
- data/lib/active_support/values/time_zone.rb +9 -7
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +2 -2
- data/lib/active_support.rb +13 -3
- metadata +106 -21
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/per_thread_registry.rb +0 -65
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
= Active Support -- Utility classes and Ruby extensions from Rails
|
1
|
+
= Active Support -- Utility classes and Ruby extensions from \Rails
|
2
2
|
|
3
3
|
Active Support is a collection of utility classes and standard library
|
4
|
-
extensions that were found useful for the Rails framework. These additions
|
4
|
+
extensions that were found useful for the \Rails framework. These additions
|
5
5
|
reside in this package so they can be loaded as needed in Ruby projects
|
6
|
-
outside of Rails.
|
6
|
+
outside of \Rails.
|
7
7
|
|
8
|
-
You can read more about the extensions in the {Active Support Core Extensions}[https://
|
8
|
+
You can read more about the extensions in the {Active Support Core Extensions}[https://guides.rubyonrails.org/active_support_core_extensions.html] guide.
|
9
9
|
|
10
10
|
== Download and installation
|
11
11
|
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
|
+
# = Actionable Errors
|
5
|
+
#
|
4
6
|
# Actionable errors lets you define actions to resolve an error.
|
5
7
|
#
|
6
|
-
# To make an error actionable, include the
|
8
|
+
# To make an error actionable, include the +ActiveSupport::ActionableError+
|
7
9
|
# module and invoke the +action+ class macro to define the action. An action
|
8
10
|
# needs a name and a block to execute.
|
9
11
|
module ActionableError
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
|
+
# = Backtrace Cleaner
|
5
|
+
#
|
4
6
|
# Backtraces often include many lines that are not relevant for the context
|
5
7
|
# under review. This makes it hard to find the signal amongst the backtrace
|
6
8
|
# noise, and adds debugging time. With a BacktraceCleaner, filters and
|
@@ -19,7 +21,7 @@ module ActiveSupport
|
|
19
21
|
# bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
|
20
22
|
# bc.clean(exception.backtrace) # perform the cleanup
|
21
23
|
#
|
22
|
-
# To reconfigure an existing BacktraceCleaner (like the default one in Rails)
|
24
|
+
# To reconfigure an existing BacktraceCleaner (like the default one in \Rails)
|
23
25
|
# and show as much data as possible, you can always call
|
24
26
|
# BacktraceCleaner#remove_silencers!, which will restore the
|
25
27
|
# backtrace to a pristine state. If you need to reconfigure an existing
|
@@ -52,11 +54,29 @@ module ActiveSupport
|
|
52
54
|
end
|
53
55
|
alias :filter :clean
|
54
56
|
|
57
|
+
# Returns the frame with all filters applied.
|
58
|
+
# returns +nil+ if the frame was silenced.
|
59
|
+
def clean_frame(frame, kind = :silent)
|
60
|
+
frame = frame.to_s
|
61
|
+
@filters.each do |f|
|
62
|
+
frame = f.call(frame.to_s)
|
63
|
+
end
|
64
|
+
|
65
|
+
case kind
|
66
|
+
when :silent
|
67
|
+
frame unless @silencers.any? { |s| s.call(frame) }
|
68
|
+
when :noise
|
69
|
+
frame if @silencers.any? { |s| s.call(frame) }
|
70
|
+
else
|
71
|
+
frame
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
55
75
|
# Adds a filter from the block provided. Each line in the backtrace will be
|
56
76
|
# mapped against this filter.
|
57
77
|
#
|
58
78
|
# # Will turn "/my/rails/root/app/models/person.rb" into "/app/models/person.rb"
|
59
|
-
# backtrace_cleaner.add_filter { |line| line.gsub(Rails.root, '') }
|
79
|
+
# backtrace_cleaner.add_filter { |line| line.gsub(Rails.root.to_s, '') }
|
60
80
|
def add_filter(&block)
|
61
81
|
@filters << block
|
62
82
|
end
|
@@ -106,7 +126,7 @@ module ActiveSupport
|
|
106
126
|
|
107
127
|
def filter_backtrace(backtrace)
|
108
128
|
@filters.each do |f|
|
109
|
-
backtrace = backtrace.map { |line| f.call(line) }
|
129
|
+
backtrace = backtrace.map { |line| f.call(line.to_s) }
|
110
130
|
end
|
111
131
|
|
112
132
|
backtrace
|
@@ -114,7 +134,7 @@ module ActiveSupport
|
|
114
134
|
|
115
135
|
def silence(backtrace)
|
116
136
|
@silencers.each do |s|
|
117
|
-
backtrace = backtrace.reject { |line| s.call(line) }
|
137
|
+
backtrace = backtrace.reject { |line| s.call(line.to_s) }
|
118
138
|
end
|
119
139
|
|
120
140
|
backtrace
|
@@ -123,7 +143,7 @@ module ActiveSupport
|
|
123
143
|
def noise(backtrace)
|
124
144
|
backtrace.select do |line|
|
125
145
|
@silencers.any? do |s|
|
126
|
-
s.call(line)
|
146
|
+
s.call(line.to_s)
|
127
147
|
end
|
128
148
|
end
|
129
149
|
end
|
@@ -4,6 +4,7 @@ require "active_support/core_ext/benchmark"
|
|
4
4
|
require "active_support/core_ext/hash/keys"
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
|
+
# = \Benchmarkable
|
7
8
|
module Benchmarkable
|
8
9
|
# Allows you to measure the execution time of a block in a template and
|
9
10
|
# records the result to the log. Wrap this block around expensive operations
|
@@ -3,6 +3,6 @@
|
|
3
3
|
begin
|
4
4
|
require "builder"
|
5
5
|
rescue LoadError => e
|
6
|
-
|
6
|
+
warn "You don't have builder installed in your application. Please add it to your Gemfile and run bundle install"
|
7
7
|
raise e
|
8
8
|
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "entry"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module Cache
|
7
|
+
class Coder # :nodoc:
|
8
|
+
def initialize(serializer, compressor, legacy_serializer: false)
|
9
|
+
@serializer = serializer
|
10
|
+
@compressor = compressor
|
11
|
+
@legacy_serializer = legacy_serializer
|
12
|
+
end
|
13
|
+
|
14
|
+
def dump(entry)
|
15
|
+
return @serializer.dump(entry) if @legacy_serializer
|
16
|
+
|
17
|
+
dump_compressed(entry, Float::INFINITY)
|
18
|
+
end
|
19
|
+
|
20
|
+
def dump_compressed(entry, threshold)
|
21
|
+
return @serializer.dump_compressed(entry, threshold) if @legacy_serializer
|
22
|
+
|
23
|
+
# If value is a string with a supported encoding, use it as the payload
|
24
|
+
# instead of passing it through the serializer.
|
25
|
+
if type = type_for_string(entry.value)
|
26
|
+
payload = entry.value.b
|
27
|
+
else
|
28
|
+
type = OBJECT_DUMP_TYPE
|
29
|
+
payload = @serializer.dump(entry.value)
|
30
|
+
end
|
31
|
+
|
32
|
+
if compressed = try_compress(payload, threshold)
|
33
|
+
payload = compressed
|
34
|
+
type = type | COMPRESSED_FLAG
|
35
|
+
end
|
36
|
+
|
37
|
+
expires_at = entry.expires_at || -1.0
|
38
|
+
|
39
|
+
version = dump_version(entry.version) if entry.version
|
40
|
+
version_length = version&.bytesize || -1
|
41
|
+
|
42
|
+
packed = SIGNATURE.b
|
43
|
+
packed << [type, expires_at, version_length].pack(PACKED_TEMPLATE)
|
44
|
+
packed << version if version
|
45
|
+
packed << payload
|
46
|
+
end
|
47
|
+
|
48
|
+
def load(dumped)
|
49
|
+
return @serializer.load(dumped) if !signature?(dumped)
|
50
|
+
|
51
|
+
type = dumped.unpack1(PACKED_TYPE_TEMPLATE)
|
52
|
+
expires_at = dumped.unpack1(PACKED_EXPIRES_AT_TEMPLATE)
|
53
|
+
version_length = dumped.unpack1(PACKED_VERSION_LENGTH_TEMPLATE)
|
54
|
+
|
55
|
+
expires_at = nil if expires_at < 0
|
56
|
+
version = load_version(dumped.byteslice(PACKED_VERSION_INDEX, version_length)) if version_length >= 0
|
57
|
+
payload = dumped.byteslice((PACKED_VERSION_INDEX + [version_length, 0].max)..)
|
58
|
+
|
59
|
+
compressor = @compressor if type & COMPRESSED_FLAG > 0
|
60
|
+
serializer = STRING_DESERIALIZERS[type & ~COMPRESSED_FLAG] || @serializer
|
61
|
+
|
62
|
+
LazyEntry.new(serializer, compressor, payload, version: version, expires_at: expires_at)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
SIGNATURE = "\x00\x11".b.freeze
|
67
|
+
|
68
|
+
OBJECT_DUMP_TYPE = 0x01
|
69
|
+
|
70
|
+
STRING_ENCODINGS = {
|
71
|
+
0x02 => Encoding::UTF_8,
|
72
|
+
0x03 => Encoding::BINARY,
|
73
|
+
0x04 => Encoding::US_ASCII,
|
74
|
+
}
|
75
|
+
|
76
|
+
COMPRESSED_FLAG = 0x80
|
77
|
+
|
78
|
+
PACKED_TEMPLATE = "CEl<"
|
79
|
+
PACKED_TYPE_TEMPLATE = "@#{SIGNATURE.bytesize}C"
|
80
|
+
PACKED_EXPIRES_AT_TEMPLATE = "@#{[0].pack(PACKED_TYPE_TEMPLATE).bytesize}E"
|
81
|
+
PACKED_VERSION_LENGTH_TEMPLATE = "@#{[0].pack(PACKED_EXPIRES_AT_TEMPLATE).bytesize}l<"
|
82
|
+
PACKED_VERSION_INDEX = [0].pack(PACKED_VERSION_LENGTH_TEMPLATE).bytesize
|
83
|
+
|
84
|
+
MARSHAL_SIGNATURE = "\x04\x08".b.freeze
|
85
|
+
|
86
|
+
class StringDeserializer
|
87
|
+
def initialize(encoding)
|
88
|
+
@encoding = encoding
|
89
|
+
end
|
90
|
+
|
91
|
+
def load(payload)
|
92
|
+
payload.force_encoding(@encoding)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
STRING_DESERIALIZERS = STRING_ENCODINGS.transform_values { |encoding| StringDeserializer.new(encoding) }
|
97
|
+
|
98
|
+
class LazyEntry < Cache::Entry
|
99
|
+
def initialize(serializer, compressor, payload, **options)
|
100
|
+
super(payload, **options)
|
101
|
+
@serializer = serializer
|
102
|
+
@compressor = compressor
|
103
|
+
@resolved = false
|
104
|
+
end
|
105
|
+
|
106
|
+
def value
|
107
|
+
if !@resolved
|
108
|
+
@value = @serializer.load(@compressor ? @compressor.inflate(@value) : @value)
|
109
|
+
@resolved = true
|
110
|
+
end
|
111
|
+
@value
|
112
|
+
end
|
113
|
+
|
114
|
+
def mismatched?(version)
|
115
|
+
super.tap { |mismatched| value if !mismatched }
|
116
|
+
rescue Cache::DeserializationError
|
117
|
+
true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def signature?(dumped)
|
122
|
+
dumped.is_a?(String) && dumped.start_with?(SIGNATURE)
|
123
|
+
end
|
124
|
+
|
125
|
+
def type_for_string(value)
|
126
|
+
STRING_ENCODINGS.key(value.encoding) if value.instance_of?(String)
|
127
|
+
end
|
128
|
+
|
129
|
+
def try_compress(string, threshold)
|
130
|
+
if @compressor && string.bytesize >= threshold
|
131
|
+
compressed = @compressor.deflate(string)
|
132
|
+
compressed if compressed.bytesize < string.bytesize
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def dump_version(version)
|
137
|
+
if version.encoding != Encoding::UTF_8 || version.start_with?(MARSHAL_SIGNATURE)
|
138
|
+
Marshal.dump(version)
|
139
|
+
else
|
140
|
+
version.b
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def load_version(dumped_version)
|
145
|
+
if dumped_version.start_with?(MARSHAL_SIGNATURE)
|
146
|
+
Marshal.load(dumped_version)
|
147
|
+
else
|
148
|
+
dumped_version.force_encoding(Encoding::UTF_8)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zlib"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module Cache
|
7
|
+
# This class is used to represent cache entries. Cache entries have a value, an optional
|
8
|
+
# expiration time, and an optional version. The expiration time is used to support the :race_condition_ttl option
|
9
|
+
# on the cache. The version is used to support the :version option on the cache for rejecting
|
10
|
+
# mismatches.
|
11
|
+
#
|
12
|
+
# Since cache entries in most instances will be serialized, the internals of this class are highly optimized
|
13
|
+
# using short instance variable names that are lazily defined.
|
14
|
+
class Entry # :nodoc:
|
15
|
+
class << self
|
16
|
+
def unpack(members)
|
17
|
+
new(members[0], expires_at: members[1], version: members[2])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :version
|
22
|
+
|
23
|
+
# Creates a new cache entry for the specified value. Options supported are
|
24
|
+
# +:compressed+, +:version+, +:expires_at+ and +:expires_in+.
|
25
|
+
def initialize(value, compressed: false, version: nil, expires_in: nil, expires_at: nil, **)
|
26
|
+
@value = value
|
27
|
+
@version = version
|
28
|
+
@created_at = 0.0
|
29
|
+
@expires_in = expires_at&.to_f || expires_in && (expires_in.to_f + Time.now.to_f)
|
30
|
+
@compressed = true if compressed
|
31
|
+
end
|
32
|
+
|
33
|
+
def value
|
34
|
+
compressed? ? uncompress(@value) : @value
|
35
|
+
end
|
36
|
+
|
37
|
+
def mismatched?(version)
|
38
|
+
@version && version && @version != version
|
39
|
+
end
|
40
|
+
|
41
|
+
# Checks if the entry is expired. The +expires_in+ parameter can override
|
42
|
+
# the value set when the entry was created.
|
43
|
+
def expired?
|
44
|
+
@expires_in && @created_at + @expires_in <= Time.now.to_f
|
45
|
+
end
|
46
|
+
|
47
|
+
def expires_at
|
48
|
+
@expires_in ? @created_at + @expires_in : nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def expires_at=(value)
|
52
|
+
if value
|
53
|
+
@expires_in = value.to_f - @created_at
|
54
|
+
else
|
55
|
+
@expires_in = nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the size of the cached value. This could be less than
|
60
|
+
# <tt>value.bytesize</tt> if the data is compressed.
|
61
|
+
def bytesize
|
62
|
+
case value
|
63
|
+
when NilClass
|
64
|
+
0
|
65
|
+
when String
|
66
|
+
@value.bytesize
|
67
|
+
else
|
68
|
+
@s ||= Marshal.dump(@value).bytesize
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def compressed? # :nodoc:
|
73
|
+
defined?(@compressed)
|
74
|
+
end
|
75
|
+
|
76
|
+
def compressed(compress_threshold)
|
77
|
+
return self if compressed?
|
78
|
+
|
79
|
+
case @value
|
80
|
+
when nil, true, false, Numeric
|
81
|
+
uncompressed_size = 0
|
82
|
+
when String
|
83
|
+
uncompressed_size = @value.bytesize
|
84
|
+
else
|
85
|
+
serialized = Marshal.dump(@value)
|
86
|
+
uncompressed_size = serialized.bytesize
|
87
|
+
end
|
88
|
+
|
89
|
+
if uncompressed_size >= compress_threshold
|
90
|
+
serialized ||= Marshal.dump(@value)
|
91
|
+
compressed = Zlib::Deflate.deflate(serialized)
|
92
|
+
|
93
|
+
if compressed.bytesize < uncompressed_size
|
94
|
+
return Entry.new(compressed, compressed: true, expires_at: expires_at, version: version)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
def local?
|
101
|
+
false
|
102
|
+
end
|
103
|
+
|
104
|
+
# Duplicates the value in a class. This is used by cache implementations that don't natively
|
105
|
+
# serialize entries to protect against accidental cache modifications.
|
106
|
+
def dup_value!
|
107
|
+
if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false)
|
108
|
+
if @value.is_a?(String)
|
109
|
+
@value = @value.dup
|
110
|
+
else
|
111
|
+
@value = Marshal.load(Marshal.dump(@value))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def pack
|
117
|
+
members = [value, expires_at, version]
|
118
|
+
members.pop while !members.empty? && members.last.nil?
|
119
|
+
members
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
def uncompress(value)
|
124
|
+
Marshal.load(Zlib::Inflate.inflate(value))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -6,10 +6,9 @@ require "uri/common"
|
|
6
6
|
|
7
7
|
module ActiveSupport
|
8
8
|
module Cache
|
9
|
-
#
|
9
|
+
# = \File \Cache \Store
|
10
10
|
#
|
11
|
-
#
|
12
|
-
# an in-memory cache inside of a block.
|
11
|
+
# A cache store implementation which stores everything on the filesystem.
|
13
12
|
class FileStore < Store
|
14
13
|
attr_reader :cache_path
|
15
14
|
|
@@ -46,14 +45,33 @@ module ActiveSupport
|
|
46
45
|
end
|
47
46
|
end
|
48
47
|
|
49
|
-
#
|
50
|
-
#
|
48
|
+
# Increment a cached integer value. Returns the updated value.
|
49
|
+
#
|
50
|
+
# If the key is unset, it starts from +0+:
|
51
|
+
#
|
52
|
+
# cache.increment("foo") # => 1
|
53
|
+
# cache.increment("bar", 100) # => 100
|
54
|
+
#
|
55
|
+
# To set a specific value, call #write:
|
56
|
+
#
|
57
|
+
# cache.write("baz", 5)
|
58
|
+
# cache.increment("baz") # => 6
|
59
|
+
#
|
51
60
|
def increment(name, amount = 1, options = nil)
|
52
61
|
modify_value(name, amount, options)
|
53
62
|
end
|
54
63
|
|
55
|
-
#
|
56
|
-
#
|
64
|
+
# Decrement a cached integer value. Returns the updated value.
|
65
|
+
#
|
66
|
+
# If the key is unset, it will be set to +-amount+.
|
67
|
+
#
|
68
|
+
# cache.decrement("foo") # => -1
|
69
|
+
#
|
70
|
+
# To set a specific value, call #write:
|
71
|
+
#
|
72
|
+
# cache.write("baz", 5)
|
73
|
+
# cache.decrement("baz") # => 4
|
74
|
+
#
|
57
75
|
def decrement(name, amount = 1, options = nil)
|
58
76
|
modify_value(name, -amount, options)
|
59
77
|
end
|
@@ -69,6 +87,10 @@ module ActiveSupport
|
|
69
87
|
end
|
70
88
|
end
|
71
89
|
|
90
|
+
def inspect # :nodoc:
|
91
|
+
"#<#{self.class.name} cache_path=#{@cache_path}, options=#{@options.inspect}>"
|
92
|
+
end
|
93
|
+
|
72
94
|
private
|
73
95
|
def read_entry(key, **options)
|
74
96
|
if payload = read_serialized_entry(key, **options)
|
@@ -106,6 +128,8 @@ module ActiveSupport
|
|
106
128
|
raise if File.exist?(key)
|
107
129
|
false
|
108
130
|
end
|
131
|
+
else
|
132
|
+
false
|
109
133
|
end
|
110
134
|
end
|
111
135
|
|
@@ -182,8 +206,8 @@ module ActiveSupport
|
|
182
206
|
end
|
183
207
|
end
|
184
208
|
|
185
|
-
# Modifies the amount of an
|
186
|
-
# If the key is not found
|
209
|
+
# Modifies the amount of an integer value that is stored in the cache.
|
210
|
+
# If the key is not found it is created and set to +amount+.
|
187
211
|
def modify_value(name, amount, options)
|
188
212
|
file_name = normalize_key(name, options)
|
189
213
|
|
@@ -194,6 +218,9 @@ module ActiveSupport
|
|
194
218
|
num = num.to_i + amount
|
195
219
|
write(name, num, options)
|
196
220
|
num
|
221
|
+
else
|
222
|
+
write(name, Integer(amount), options)
|
223
|
+
amount
|
197
224
|
end
|
198
225
|
end
|
199
226
|
end
|