activesupport 7.1.3.4 → 7.2.1
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 +123 -1084
- data/lib/active_support/array_inquirer.rb +1 -1
- data/lib/active_support/backtrace_cleaner.rb +15 -3
- data/lib/active_support/broadcast_logger.rb +5 -4
- data/lib/active_support/cache/file_store.rb +15 -10
- data/lib/active_support/cache/mem_cache_store.rb +16 -74
- data/lib/active_support/cache/memory_store.rb +2 -1
- data/lib/active_support/cache/redis_cache_store.rb +16 -13
- data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
- data/lib/active_support/cache.rb +61 -68
- data/lib/active_support/callbacks.rb +74 -113
- data/lib/active_support/code_generator.rb +15 -10
- data/lib/active_support/core_ext/array/conversions.rb +0 -2
- data/lib/active_support/core_ext/class/subclasses.rb +15 -35
- data/lib/active_support/core_ext/date/blank.rb +4 -0
- data/lib/active_support/core_ext/date/conversions.rb +0 -2
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +28 -1
- data/lib/active_support/core_ext/date_time/blank.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +0 -4
- data/lib/active_support/core_ext/digest/uuid.rb +6 -0
- data/lib/active_support/core_ext/erb/util.rb +5 -0
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
- data/lib/active_support/core_ext/module/delegation.rb +20 -148
- data/lib/active_support/core_ext/module/deprecation.rb +1 -4
- data/lib/active_support/core_ext/numeric/conversions.rb +3 -3
- data/lib/active_support/core_ext/object/blank.rb +45 -1
- data/lib/active_support/core_ext/object/duplicable.rb +24 -15
- data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
- data/lib/active_support/core_ext/object/json.rb +1 -1
- data/lib/active_support/core_ext/object/with.rb +5 -3
- data/lib/active_support/core_ext/pathname/blank.rb +4 -0
- data/lib/active_support/core_ext/range/overlap.rb +1 -1
- data/lib/active_support/core_ext/securerandom.rb +8 -24
- data/lib/active_support/core_ext/string/conversions.rb +1 -1
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +0 -7
- data/lib/active_support/core_ext/time/calculations.rb +18 -28
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +0 -2
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/current_attributes.rb +34 -40
- data/lib/active_support/delegation.rb +202 -0
- data/lib/active_support/dependencies/autoload.rb +0 -12
- data/lib/active_support/deprecation/constant_accessor.rb +47 -26
- data/lib/active_support/deprecation/proxy_wrappers.rb +9 -12
- data/lib/active_support/deprecation/reporting.rb +7 -2
- data/lib/active_support/deprecation.rb +8 -5
- data/lib/active_support/descendants_tracker.rb +9 -87
- data/lib/active_support/duration/iso8601_parser.rb +2 -2
- data/lib/active_support/duration/iso8601_serializer.rb +1 -2
- data/lib/active_support/duration.rb +11 -6
- data/lib/active_support/error_reporter.rb +41 -3
- data/lib/active_support/evented_file_update_checker.rb +0 -1
- data/lib/active_support/execution_wrapper.rb +0 -1
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/fork_tracker.rb +2 -38
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +6 -8
- data/lib/active_support/html_safe_translation.rb +7 -4
- data/lib/active_support/json/encoding.rb +1 -1
- data/lib/active_support/log_subscriber.rb +1 -12
- data/lib/active_support/logger.rb +15 -2
- data/lib/active_support/logger_thread_safe_level.rb +0 -8
- data/lib/active_support/message_pack/extensions.rb +15 -2
- data/lib/active_support/message_verifier.rb +12 -0
- data/lib/active_support/messages/codec.rb +1 -1
- data/lib/active_support/multibyte/chars.rb +2 -2
- data/lib/active_support/notifications/fanout.rb +4 -7
- data/lib/active_support/notifications/instrumenter.rb +32 -21
- data/lib/active_support/notifications.rb +28 -27
- data/lib/active_support/number_helper/number_converter.rb +2 -2
- data/lib/active_support/option_merger.rb +2 -2
- data/lib/active_support/ordered_options.rb +53 -15
- data/lib/active_support/proxy_object.rb +8 -5
- data/lib/active_support/railtie.rb +4 -11
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +1 -0
- data/lib/active_support/syntax_error_proxy.rb +1 -11
- data/lib/active_support/tagged_logging.rb +4 -1
- data/lib/active_support/test_case.rb +3 -1
- data/lib/active_support/testing/assertions.rb +4 -4
- data/lib/active_support/testing/constant_stubbing.rb +30 -8
- data/lib/active_support/testing/deprecation.rb +5 -12
- data/lib/active_support/testing/isolation.rb +18 -8
- data/lib/active_support/testing/method_call_assertions.rb +2 -16
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/strict_warnings.rb +5 -4
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +3 -3
- data/lib/active_support/time_with_zone.rb +7 -3
- data/lib/active_support/values/time_zone.rb +10 -1
- data/lib/active_support/xml_mini.rb +11 -2
- data/lib/active_support.rb +3 -2
- metadata +35 -15
- data/lib/active_support/deprecation/instance_delegator.rb +0 -65
- data/lib/active_support/ruby_features.rb +0 -7
@@ -102,12 +102,12 @@ module ActiveSupport
|
|
102
102
|
raise_parsing_error("is empty duration") if parts.empty?
|
103
103
|
|
104
104
|
# Mixing any of Y, M, D with W is invalid.
|
105
|
-
if parts.key?(:weeks) &&
|
105
|
+
if parts.key?(:weeks) && parts.keys.intersect?(DATE_COMPONENTS)
|
106
106
|
raise_parsing_error("mixing weeks with other date parts not allowed")
|
107
107
|
end
|
108
108
|
|
109
109
|
# Specifying an empty T part is invalid.
|
110
|
-
if mode == :time &&
|
110
|
+
if mode == :time && !parts.keys.intersect?(TIME_COMPONENTS)
|
111
111
|
raise_parsing_error("time part marker is present but time part is empty")
|
112
112
|
end
|
113
113
|
|
@@ -35,7 +35,6 @@ module ActiveSupport
|
|
35
35
|
# Return pair of duration's parts and whole duration sign.
|
36
36
|
# Parts are summarized (as they can become repetitive due to addition, etc).
|
37
37
|
# Zero parts are removed as not significant.
|
38
|
-
# If all parts are negative it will negate all of them and return minus as a sign.
|
39
38
|
def normalize
|
40
39
|
parts = @duration.parts.each_with_object(Hash.new(0)) do |(k, v), p|
|
41
40
|
p[k] += v unless v.zero?
|
@@ -50,7 +49,7 @@ module ActiveSupport
|
|
50
49
|
end
|
51
50
|
|
52
51
|
def week_mixed_with_date?(parts)
|
53
|
-
parts.key?(:weeks) &&
|
52
|
+
parts.key?(:weeks) && parts.keys.intersect?(DATE_COMPONENTS)
|
54
53
|
end
|
55
54
|
|
56
55
|
def format_seconds(seconds)
|
@@ -14,7 +14,7 @@ module ActiveSupport
|
|
14
14
|
class Duration
|
15
15
|
class Scalar < Numeric # :nodoc:
|
16
16
|
attr_reader :value
|
17
|
-
delegate :to_i, :to_f, :to_s, to:
|
17
|
+
delegate :to_i, :to_f, :to_s, to: :@value
|
18
18
|
|
19
19
|
def initialize(value)
|
20
20
|
@value = value
|
@@ -221,6 +221,8 @@ module ActiveSupport
|
|
221
221
|
end
|
222
222
|
end
|
223
223
|
|
224
|
+
Delegation.generate(self, [:to_f, :positive?, :negative?, :zero?, :abs], to: :@value, as: Integer, nilable: false)
|
225
|
+
|
224
226
|
def initialize(value, parts, variable = nil) # :nodoc:
|
225
227
|
@value, @parts = value, parts
|
226
228
|
@parts.reject! { |k, v| v.zero? } unless value == 0
|
@@ -232,7 +234,10 @@ module ActiveSupport
|
|
232
234
|
end
|
233
235
|
end
|
234
236
|
|
235
|
-
# Returns a copy of the parts hash that defines the duration
|
237
|
+
# Returns a copy of the parts hash that defines the duration.
|
238
|
+
#
|
239
|
+
# 5.minutes.parts # => {:minutes=>5}
|
240
|
+
# 3.years.parts # => {:years=>3}
|
236
241
|
def parts
|
237
242
|
@parts.dup
|
238
243
|
end
|
@@ -366,8 +371,8 @@ module ActiveSupport
|
|
366
371
|
# 1.year.to_i # => 31556952
|
367
372
|
#
|
368
373
|
# In such cases, Ruby's core
|
369
|
-
# Date[https://ruby-
|
370
|
-
# Time[https://ruby-
|
374
|
+
# Date[https://docs.ruby-lang.org/en/master/Date.html] and
|
375
|
+
# Time[https://docs.ruby-lang.org/en/master/Time.html] should be used for precision
|
371
376
|
# date and time arithmetic.
|
372
377
|
def to_i
|
373
378
|
@value.to_i
|
@@ -504,8 +509,8 @@ module ActiveSupport
|
|
504
509
|
value.respond_to?(method)
|
505
510
|
end
|
506
511
|
|
507
|
-
def method_missing(
|
508
|
-
value.public_send(
|
512
|
+
def method_missing(...)
|
513
|
+
value.public_send(...)
|
509
514
|
end
|
510
515
|
|
511
516
|
def raise_type_error(other)
|
@@ -26,12 +26,16 @@ module ActiveSupport
|
|
26
26
|
class ErrorReporter
|
27
27
|
SEVERITIES = %i(error warning info)
|
28
28
|
DEFAULT_SOURCE = "application"
|
29
|
+
DEFAULT_RESCUE = [StandardError].freeze
|
29
30
|
|
30
|
-
attr_accessor :logger
|
31
|
+
attr_accessor :logger, :debug_mode
|
32
|
+
|
33
|
+
UnexpectedError = Class.new(Exception)
|
31
34
|
|
32
35
|
def initialize(*subscribers, logger: nil)
|
33
36
|
@subscribers = subscribers.flatten
|
34
37
|
@logger = logger
|
38
|
+
@debug_mode = false
|
35
39
|
end
|
36
40
|
|
37
41
|
# Evaluates the given block, reporting and swallowing any unhandled error.
|
@@ -72,7 +76,7 @@ module ActiveSupport
|
|
72
76
|
# source of the error. Subscribers can use this value to ignore certain
|
73
77
|
# errors. Defaults to <tt>"application"</tt>.
|
74
78
|
def handle(*error_classes, severity: :warning, context: {}, fallback: nil, source: DEFAULT_SOURCE)
|
75
|
-
error_classes =
|
79
|
+
error_classes = DEFAULT_RESCUE if error_classes.empty?
|
76
80
|
yield
|
77
81
|
rescue *error_classes => error
|
78
82
|
report(error, handled: true, severity: severity, context: context, source: source)
|
@@ -108,13 +112,47 @@ module ActiveSupport
|
|
108
112
|
# source of the error. Subscribers can use this value to ignore certain
|
109
113
|
# errors. Defaults to <tt>"application"</tt>.
|
110
114
|
def record(*error_classes, severity: :error, context: {}, source: DEFAULT_SOURCE)
|
111
|
-
error_classes =
|
115
|
+
error_classes = DEFAULT_RESCUE if error_classes.empty?
|
112
116
|
yield
|
113
117
|
rescue *error_classes => error
|
114
118
|
report(error, handled: false, severity: severity, context: context, source: source)
|
115
119
|
raise
|
116
120
|
end
|
117
121
|
|
122
|
+
# Either report the given error when in production, or raise it when in development or test.
|
123
|
+
#
|
124
|
+
# When called in production, after the error is reported, this method will return
|
125
|
+
# nil and execution will continue.
|
126
|
+
#
|
127
|
+
# When called in development, the original error is wrapped in a different error class to ensure
|
128
|
+
# it's not being rescued higher in the stack and will be surfaced to the developer.
|
129
|
+
#
|
130
|
+
# This method is intended for reporting violated assertions about preconditions, or similar
|
131
|
+
# cases that can and should be gracefully handled in production, but that aren't supposed to happen.
|
132
|
+
#
|
133
|
+
# The error can be either an exception instance or a String.
|
134
|
+
#
|
135
|
+
# example:
|
136
|
+
#
|
137
|
+
# def edit
|
138
|
+
# if published?
|
139
|
+
# Rails.error.unexpected("[BUG] Attempting to edit a published article, that shouldn't be possible")
|
140
|
+
# return false
|
141
|
+
# end
|
142
|
+
# # ...
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
def unexpected(error, severity: :warning, context: {}, source: DEFAULT_SOURCE)
|
146
|
+
error = RuntimeError.new(error) if error.is_a?(String)
|
147
|
+
error.set_backtrace(caller(1)) if error.backtrace.nil?
|
148
|
+
|
149
|
+
if @debug_mode
|
150
|
+
raise UnexpectedError, "#{error.class.name}: #{error.message}", error.backtrace, cause: error
|
151
|
+
else
|
152
|
+
report(error, handled: true, severity: severity, context: context, source: source)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
118
156
|
# Register a new error subscriber. The subscriber must respond to
|
119
157
|
#
|
120
158
|
# report(Exception, handled: Boolean, severity: (:error OR :warning OR :info), context: Hash, source: String)
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
4
|
module ForkTracker # :nodoc:
|
5
|
-
module
|
5
|
+
module CoreExt
|
6
6
|
def _fork
|
7
7
|
pid = super
|
8
8
|
if pid == 0
|
@@ -12,27 +12,6 @@ module ActiveSupport
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
module CoreExt
|
16
|
-
def fork(...)
|
17
|
-
if block_given?
|
18
|
-
super do
|
19
|
-
ForkTracker.check!
|
20
|
-
yield
|
21
|
-
end
|
22
|
-
else
|
23
|
-
unless pid = super
|
24
|
-
ForkTracker.check!
|
25
|
-
end
|
26
|
-
pid
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
module CoreExtPrivate
|
32
|
-
include CoreExt
|
33
|
-
private :fork
|
34
|
-
end
|
35
|
-
|
36
15
|
@pid = Process.pid
|
37
16
|
@callbacks = []
|
38
17
|
|
@@ -45,23 +24,8 @@ module ActiveSupport
|
|
45
24
|
end
|
46
25
|
end
|
47
26
|
|
48
|
-
if Process.respond_to?(:_fork) # Ruby 3.1+
|
49
|
-
def check!
|
50
|
-
# We trust the `_fork` callback
|
51
|
-
end
|
52
|
-
else
|
53
|
-
alias_method :check!, :after_fork_callback
|
54
|
-
end
|
55
|
-
|
56
27
|
def hook!
|
57
|
-
|
58
|
-
::Process.singleton_class.prepend(ModernCoreExt)
|
59
|
-
elsif Process.respond_to?(:fork)
|
60
|
-
::Object.prepend(CoreExtPrivate) if RUBY_VERSION < "3.0"
|
61
|
-
::Kernel.prepend(CoreExtPrivate)
|
62
|
-
::Kernel.singleton_class.prepend(CoreExt)
|
63
|
-
::Process.singleton_class.prepend(CoreExt)
|
64
|
-
end
|
28
|
+
::Process.singleton_class.prepend(CoreExt)
|
65
29
|
end
|
66
30
|
|
67
31
|
def after_fork(&block)
|
@@ -387,15 +387,13 @@ module ActiveSupport
|
|
387
387
|
_new_hash
|
388
388
|
end
|
389
389
|
|
390
|
+
def to_proc
|
391
|
+
proc { |key| self[key] }
|
392
|
+
end
|
393
|
+
|
390
394
|
private
|
391
|
-
|
392
|
-
|
393
|
-
key.kind_of?(Symbol) ? key.name : key
|
394
|
-
end
|
395
|
-
else
|
396
|
-
def convert_key(key)
|
397
|
-
key.kind_of?(Symbol) ? key.to_s : key
|
398
|
-
end
|
395
|
+
def convert_key(key)
|
396
|
+
Symbol === key ? key.name : key
|
399
397
|
end
|
400
398
|
|
401
399
|
def convert_value(value, conversion: nil)
|
@@ -9,11 +9,14 @@ module ActiveSupport
|
|
9
9
|
html_safe_options = html_escape_translation_options(options)
|
10
10
|
|
11
11
|
exception = false
|
12
|
+
|
12
13
|
exception_handler = ->(*args) do
|
13
14
|
exception = true
|
14
15
|
I18n.exception_handler.call(*args)
|
15
16
|
end
|
17
|
+
|
16
18
|
translation = I18n.translate(key, **html_safe_options, exception_handler: exception_handler)
|
19
|
+
|
17
20
|
if exception
|
18
21
|
translation
|
19
22
|
else
|
@@ -24,11 +27,11 @@ module ActiveSupport
|
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
30
|
+
def html_safe_translation_key?(key)
|
31
|
+
/(?:_|\b)html\z/.match?(key)
|
32
|
+
end
|
31
33
|
|
34
|
+
private
|
32
35
|
def html_escape_translation_options(options)
|
33
36
|
options.each do |name, value|
|
34
37
|
unless i18n_option?(name) || (name == :count && value.is_a?(Numeric))
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "active_support/core_ext/module/attribute_accessors"
|
4
4
|
require "active_support/core_ext/class/attribute"
|
5
|
+
require "active_support/core_ext/enumerable"
|
5
6
|
require "active_support/subscriber"
|
6
7
|
require "active_support/deprecation/proxy_wrappers"
|
7
8
|
|
@@ -61,10 +62,6 @@ module ActiveSupport
|
|
61
62
|
# that all logs are flushed, and it is called in Rails::Rack::Logger after a
|
62
63
|
# request finishes.
|
63
64
|
class LogSubscriber < Subscriber
|
64
|
-
# Embed in a String to clear all previous ANSI sequences.
|
65
|
-
CLEAR = ActiveSupport::Deprecation::DeprecatedObjectProxy.new("\e[0m", "CLEAR is deprecated! Use MODES[:clear] instead.", ActiveSupport.deprecator)
|
66
|
-
BOLD = ActiveSupport::Deprecation::DeprecatedObjectProxy.new("\e[1m", "BOLD is deprecated! Use MODES[:bold] instead.", ActiveSupport.deprecator)
|
67
|
-
|
68
65
|
# ANSI sequence modes
|
69
66
|
MODES = {
|
70
67
|
clear: 0,
|
@@ -181,14 +178,6 @@ module ActiveSupport
|
|
181
178
|
end
|
182
179
|
|
183
180
|
def mode_from(options)
|
184
|
-
if options.is_a?(TrueClass) || options.is_a?(FalseClass)
|
185
|
-
ActiveSupport.deprecator.warn(<<~MSG.squish)
|
186
|
-
Bolding log text with a positional boolean is deprecated and will be removed
|
187
|
-
in Rails 7.2. Use an option hash instead (eg. `color("my text", :red, bold: true)`).
|
188
|
-
MSG
|
189
|
-
options = { bold: options }
|
190
|
-
end
|
191
|
-
|
192
181
|
modes = MODES.values_at(*options.compact_blank.keys)
|
193
182
|
|
194
183
|
"\e[#{modes.join(";")}m" if modes.any?
|
@@ -13,6 +13,10 @@ module ActiveSupport
|
|
13
13
|
# logger = Logger.new(STDOUT)
|
14
14
|
# ActiveSupport::Logger.logger_outputs_to?(logger, STDOUT)
|
15
15
|
# # => true
|
16
|
+
#
|
17
|
+
# logger = Logger.new('/var/log/rails.log')
|
18
|
+
# ActiveSupport::Logger.logger_outputs_to?(logger, '/var/log/rails.log')
|
19
|
+
# # => true
|
16
20
|
def self.logger_outputs_to?(logger, *sources)
|
17
21
|
loggers = if logger.is_a?(BroadcastLogger)
|
18
22
|
logger.broadcasts
|
@@ -21,9 +25,9 @@ module ActiveSupport
|
|
21
25
|
end
|
22
26
|
|
23
27
|
logdevs = loggers.map { |logger| logger.instance_variable_get(:@logdev) }
|
24
|
-
logger_sources = logdevs.filter_map { |logdev| logdev.
|
28
|
+
logger_sources = logdevs.filter_map { |logdev| logdev.try(:filename) || logdev.try(:dev) }
|
25
29
|
|
26
|
-
(sources
|
30
|
+
normalize_sources(sources).intersect?(normalize_sources(logger_sources))
|
27
31
|
end
|
28
32
|
|
29
33
|
def initialize(*args, **kwargs)
|
@@ -38,5 +42,14 @@ module ActiveSupport
|
|
38
42
|
"#{String === msg ? msg : msg.inspect}\n"
|
39
43
|
end
|
40
44
|
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def self.normalize_sources(sources)
|
48
|
+
sources.map do |source|
|
49
|
+
source = source.path if source.respond_to?(:path)
|
50
|
+
source = File.realpath(source) if source.is_a?(String) && File.exist?(source)
|
51
|
+
source
|
52
|
+
end
|
53
|
+
end
|
41
54
|
end
|
42
55
|
end
|
@@ -7,14 +7,6 @@ module ActiveSupport
|
|
7
7
|
module LoggerThreadSafeLevel # :nodoc:
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
|
-
Logger::Severity.constants.each do |severity|
|
11
|
-
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
|
12
|
-
def #{severity.downcase}? # def debug?
|
13
|
-
Logger::#{severity} >= level # DEBUG >= level
|
14
|
-
end # end
|
15
|
-
EOT
|
16
|
-
end
|
17
|
-
|
18
10
|
def local_level
|
19
11
|
IsolatedExecutionState[local_level_key]
|
20
12
|
end
|
@@ -86,8 +86,9 @@ module ActiveSupport
|
|
86
86
|
unpacker: URI.method(:parse)
|
87
87
|
|
88
88
|
registry.register_type 14, IPAddr,
|
89
|
-
packer: :
|
90
|
-
unpacker: :
|
89
|
+
packer: method(:write_ipaddr),
|
90
|
+
unpacker: method(:read_ipaddr),
|
91
|
+
recursive: true
|
91
92
|
|
92
93
|
registry.register_type 15, Pathname,
|
93
94
|
packer: :to_s,
|
@@ -221,6 +222,18 @@ module ActiveSupport
|
|
221
222
|
Set.new(unpacker.read)
|
222
223
|
end
|
223
224
|
|
225
|
+
def write_ipaddr(ipaddr, packer)
|
226
|
+
if ipaddr.prefix < 32 || (ipaddr.ipv6? && ipaddr.prefix < 128)
|
227
|
+
packer.write("#{ipaddr}/#{ipaddr.prefix}")
|
228
|
+
else
|
229
|
+
packer.write(ipaddr.to_s)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def read_ipaddr(unpacker)
|
234
|
+
IPAddr.new(unpacker.read)
|
235
|
+
end
|
236
|
+
|
224
237
|
def write_hash_with_indifferent_access(hwia, packer)
|
225
238
|
packer.write(hwia.to_h)
|
226
239
|
end
|
@@ -30,6 +30,18 @@ module ActiveSupport
|
|
30
30
|
# self.current_user = User.find(id)
|
31
31
|
# end
|
32
32
|
#
|
33
|
+
# === Signing is not encryption
|
34
|
+
#
|
35
|
+
# The signed messages are not encrypted. The payload is merely encoded (Base64 by default) and can be decoded by
|
36
|
+
# anyone. The signature is just assuring that the message wasn't tampered with. For example:
|
37
|
+
#
|
38
|
+
# message = Rails.application.message_verifier('my_purpose').generate('never put secrets here')
|
39
|
+
# # => "BAhJIhtuZXZlciBwdXQgc2VjcmV0cyBoZXJlBjoGRVQ=--a0c1c0827919da5e949e989c971249355735e140"
|
40
|
+
# Base64.decode64(message.split("--").first) # no key needed
|
41
|
+
# # => 'never put secrets here'
|
42
|
+
#
|
43
|
+
# If you also need to encrypt the contents, you must use ActiveSupport::MessageEncryptor instead.
|
44
|
+
#
|
33
45
|
# === Confine messages to a specific purpose
|
34
46
|
#
|
35
47
|
# It's not recommended to use the same verifier for different purposes in your application.
|
@@ -28,7 +28,7 @@ module ActiveSupport
|
|
28
28
|
|
29
29
|
def decode(encoded, url_safe: @url_safe)
|
30
30
|
url_safe ? ::Base64.urlsafe_decode64(encoded) : ::Base64.strict_decode64(encoded)
|
31
|
-
rescue
|
31
|
+
rescue StandardError => error
|
32
32
|
throw :invalid_message_format, error
|
33
33
|
end
|
34
34
|
|
@@ -59,8 +59,8 @@ module ActiveSupport # :nodoc:
|
|
59
59
|
end
|
60
60
|
|
61
61
|
# Forward all undefined methods to the wrapped string.
|
62
|
-
def method_missing(method,
|
63
|
-
result = @wrapped_string.__send__(method,
|
62
|
+
def method_missing(method, ...)
|
63
|
+
result = @wrapped_string.__send__(method, ...)
|
64
64
|
if method.end_with?("!")
|
65
65
|
self if result
|
66
66
|
else
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "mutex_m"
|
4
3
|
require "concurrent/map"
|
5
4
|
require "set"
|
6
5
|
require "active_support/core_ext/object/try"
|
@@ -49,15 +48,13 @@ module ActiveSupport
|
|
49
48
|
#
|
50
49
|
# This class is thread safe. All methods are reentrant.
|
51
50
|
class Fanout
|
52
|
-
include Mutex_m
|
53
|
-
|
54
51
|
def initialize
|
52
|
+
@mutex = Mutex.new
|
55
53
|
@string_subscribers = Concurrent::Map.new { |h, k| h.compute_if_absent(k) { [] } }
|
56
54
|
@other_subscribers = []
|
57
55
|
@all_listeners_for = Concurrent::Map.new
|
58
56
|
@groups_for = Concurrent::Map.new
|
59
57
|
@silenceable_groups_for = Concurrent::Map.new
|
60
|
-
super
|
61
58
|
end
|
62
59
|
|
63
60
|
def inspect # :nodoc:
|
@@ -67,7 +64,7 @@ module ActiveSupport
|
|
67
64
|
|
68
65
|
def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
|
69
66
|
subscriber = Subscribers.new(pattern, callable || block, monotonic)
|
70
|
-
synchronize do
|
67
|
+
@mutex.synchronize do
|
71
68
|
case pattern
|
72
69
|
when String
|
73
70
|
@string_subscribers[pattern] << subscriber
|
@@ -83,7 +80,7 @@ module ActiveSupport
|
|
83
80
|
end
|
84
81
|
|
85
82
|
def unsubscribe(subscriber_or_name)
|
86
|
-
synchronize do
|
83
|
+
@mutex.synchronize do
|
87
84
|
case subscriber_or_name
|
88
85
|
when String
|
89
86
|
@string_subscribers[subscriber_or_name].clear
|
@@ -300,7 +297,7 @@ module ActiveSupport
|
|
300
297
|
|
301
298
|
def all_listeners_for(name)
|
302
299
|
# this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
|
303
|
-
@all_listeners_for[name] || synchronize do
|
300
|
+
@all_listeners_for[name] || @mutex.synchronize do
|
304
301
|
# use synchronisation when accessing @subscribers
|
305
302
|
@all_listeners_for[name] ||=
|
306
303
|
@string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
|
@@ -104,7 +104,7 @@ module ActiveSupport
|
|
104
104
|
end
|
105
105
|
|
106
106
|
class Event
|
107
|
-
attr_reader :name, :
|
107
|
+
attr_reader :name, :transaction_id
|
108
108
|
attr_accessor :payload
|
109
109
|
|
110
110
|
def initialize(name, start, ending, transaction_id, payload)
|
@@ -117,9 +117,19 @@ module ActiveSupport
|
|
117
117
|
@cpu_time_finish = 0.0
|
118
118
|
@allocation_count_start = 0
|
119
119
|
@allocation_count_finish = 0
|
120
|
+
@gc_time_start = 0
|
121
|
+
@gc_time_finish = 0
|
120
122
|
end
|
121
123
|
|
122
|
-
def
|
124
|
+
def time
|
125
|
+
@time / 1000.0 if @time
|
126
|
+
end
|
127
|
+
|
128
|
+
def end
|
129
|
+
@end / 1000.0 if @end
|
130
|
+
end
|
131
|
+
|
132
|
+
def record # :nodoc:
|
123
133
|
start!
|
124
134
|
begin
|
125
135
|
yield payload if block_given?
|
@@ -136,12 +146,14 @@ module ActiveSupport
|
|
136
146
|
def start!
|
137
147
|
@time = now
|
138
148
|
@cpu_time_start = now_cpu
|
149
|
+
@gc_time_start = now_gc
|
139
150
|
@allocation_count_start = now_allocations
|
140
151
|
end
|
141
152
|
|
142
153
|
# Record information at the time this event finishes
|
143
154
|
def finish!
|
144
155
|
@cpu_time_finish = now_cpu
|
156
|
+
@gc_time_finish = now_gc
|
145
157
|
@end = now
|
146
158
|
@allocation_count_finish = now_allocations
|
147
159
|
end
|
@@ -165,28 +177,17 @@ module ActiveSupport
|
|
165
177
|
@allocation_count_finish - @allocation_count_start
|
166
178
|
end
|
167
179
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
EOM
|
173
|
-
[]
|
174
|
-
end
|
175
|
-
|
176
|
-
def parent_of?(event) # :nodoc:
|
177
|
-
ActiveSupport.deprecator.warn <<~EOM
|
178
|
-
ActiveSupport::Notifications::Event#parent_of? is deprecated and will
|
179
|
-
be removed in Rails 7.2.
|
180
|
-
EOM
|
181
|
-
start = (time - event.time) * 1000
|
182
|
-
start <= 0 && (start + duration >= event.duration)
|
180
|
+
# Returns the time spent in GC (in milliseconds) between the call to #start!
|
181
|
+
# and the call to #finish!
|
182
|
+
def gc_time
|
183
|
+
(@gc_time_finish - @gc_time_start) / 1_000_000.0
|
183
184
|
end
|
184
185
|
|
185
186
|
# Returns the difference in milliseconds between when the execution of the
|
186
187
|
# event started and when it ended.
|
187
188
|
#
|
188
|
-
# ActiveSupport::Notifications.subscribe('wait') do
|
189
|
-
# @event =
|
189
|
+
# ActiveSupport::Notifications.subscribe('wait') do |event|
|
190
|
+
# @event = event
|
190
191
|
# end
|
191
192
|
#
|
192
193
|
# ActiveSupport::Notifications.instrument('wait') do
|
@@ -195,7 +196,7 @@ module ActiveSupport
|
|
195
196
|
#
|
196
197
|
# @event.duration # => 1000.138
|
197
198
|
def duration
|
198
|
-
|
199
|
+
@end - @time
|
199
200
|
end
|
200
201
|
|
201
202
|
private
|
@@ -210,11 +211,21 @@ module ActiveSupport
|
|
210
211
|
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_millisecond)
|
211
212
|
end
|
212
213
|
rescue
|
213
|
-
def now_cpu
|
214
|
+
def now_cpu
|
214
215
|
0.0
|
215
216
|
end
|
216
217
|
end
|
217
218
|
|
219
|
+
if GC.respond_to?(:total_time)
|
220
|
+
def now_gc
|
221
|
+
GC.total_time
|
222
|
+
end
|
223
|
+
else
|
224
|
+
def now_gc
|
225
|
+
0
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
218
229
|
if GC.stat.key?(:total_allocated_objects)
|
219
230
|
def now_allocations
|
220
231
|
GC.stat(:total_allocated_objects)
|