activesupport 1.2.4 → 8.1.2
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 +7 -0
- data/CHANGELOG.md +505 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +40 -0
- data/lib/active_support/actionable_error.rb +50 -0
- data/lib/active_support/all.rb +5 -0
- data/lib/active_support/array_inquirer.rb +50 -0
- data/lib/active_support/backtrace_cleaner.rb +234 -0
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +53 -0
- data/lib/active_support/broadcast_logger.rb +238 -0
- data/lib/active_support/builder.rb +8 -0
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +244 -0
- data/lib/active_support/cache/mem_cache_store.rb +288 -0
- data/lib/active_support/cache/memory_store.rb +264 -0
- data/lib/active_support/cache/null_store.rb +62 -0
- data/lib/active_support/cache/redis_cache_store.rb +498 -0
- data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
- data/lib/active_support/cache/strategy/local_cache.rb +246 -0
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +1170 -0
- data/lib/active_support/callbacks.rb +960 -0
- data/lib/active_support/class_attribute.rb +33 -0
- data/lib/active_support/code_generator.rb +79 -0
- data/lib/active_support/concern.rb +217 -0
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +225 -0
- data/lib/active_support/concurrency/thread_monitor.rb +55 -0
- data/lib/active_support/configurable.rb +193 -0
- data/lib/active_support/configuration_file.rb +60 -0
- data/lib/active_support/continuous_integration.rb +145 -0
- data/lib/active_support/core_ext/array/access.rb +100 -0
- data/lib/active_support/core_ext/array/conversions.rb +209 -26
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +31 -0
- data/lib/active_support/core_ext/array/grouping.rb +109 -0
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +48 -0
- data/lib/active_support/core_ext/array.rb +8 -4
- data/lib/active_support/core_ext/benchmark.rb +6 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
- data/lib/active_support/core_ext/big_decimal.rb +3 -0
- data/lib/active_support/core_ext/class/attribute.rb +137 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/class/subclasses.rb +24 -0
- data/lib/active_support/core_ext/class.rb +4 -0
- data/lib/active_support/core_ext/date/acts_like.rb +10 -0
- data/lib/active_support/core_ext/date/blank.rb +18 -0
- data/lib/active_support/core_ext/date/calculations.rb +161 -0
- data/lib/active_support/core_ext/date/conversions.rb +95 -28
- data/lib/active_support/core_ext/date/zones.rb +8 -0
- data/lib/active_support/core_ext/date.rb +6 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +374 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +23 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +16 -0
- data/lib/active_support/core_ext/date_time/blank.rb +18 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +215 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +108 -0
- data/lib/active_support/core_ext/date_time.rb +7 -0
- data/lib/active_support/core_ext/digest/uuid.rb +76 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +277 -7
- data/lib/active_support/core_ext/erb/util.rb +201 -0
- data/lib/active_support/core_ext/file/atomic.rb +72 -0
- data/lib/active_support/core_ext/file.rb +3 -0
- data/lib/active_support/core_ext/hash/conversions.rb +262 -0
- data/lib/active_support/core_ext/hash/deep_merge.rb +43 -0
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +12 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +19 -55
- data/lib/active_support/core_ext/hash/keys.rb +134 -44
- data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -22
- data/lib/active_support/core_ext/hash/slice.rb +27 -0
- data/lib/active_support/core_ext/hash.rb +9 -8
- data/lib/active_support/core_ext/integer/inflections.rb +29 -13
- data/lib/active_support/core_ext/integer/multiple.rb +12 -0
- data/lib/active_support/core_ext/integer/time.rb +22 -0
- data/lib/active_support/core_ext/integer.rb +4 -6
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +45 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +8 -0
- data/lib/active_support/core_ext/kernel.rb +4 -78
- data/lib/active_support/core_ext/load_error.rb +6 -35
- data/lib/active_support/core_ext/module/aliasing.rb +31 -0
- data/lib/active_support/core_ext/module/anonymous.rb +30 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +48 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +214 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +175 -0
- data/lib/active_support/core_ext/module/concerning.rb +140 -0
- data/lib/active_support/core_ext/module/delegation.rb +225 -0
- data/lib/active_support/core_ext/module/deprecation.rb +25 -0
- data/lib/active_support/core_ext/module/introspection.rb +65 -0
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +17 -0
- data/lib/active_support/core_ext/module.rb +13 -0
- data/lib/active_support/core_ext/name_error.rb +59 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +73 -42
- data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
- data/lib/active_support/core_ext/numeric/time.rb +64 -57
- data/lib/active_support/core_ext/numeric.rb +4 -6
- data/lib/active_support/core_ext/object/acts_like.rb +45 -0
- data/lib/active_support/core_ext/object/blank.rb +199 -0
- data/lib/active_support/core_ext/object/conversions.rb +6 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +71 -0
- data/lib/active_support/core_ext/object/duplicable.rb +69 -0
- data/lib/active_support/core_ext/object/inclusion.rb +37 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +32 -0
- data/lib/active_support/core_ext/object/json.rb +267 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -0
- data/lib/active_support/core_ext/object/to_query.rb +93 -0
- data/lib/active_support/core_ext/object/try.rb +158 -0
- data/lib/active_support/core_ext/object/with.rb +46 -0
- data/lib/active_support/core_ext/object/with_options.rb +101 -0
- data/lib/active_support/core_ext/object.rb +17 -0
- data/lib/active_support/core_ext/pathname/blank.rb +20 -0
- data/lib/active_support/core_ext/pathname/existence.rb +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +58 -17
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range/sole.rb +17 -0
- data/lib/active_support/core_ext/range.rb +5 -4
- data/lib/active_support/core_ext/regexp.rb +14 -0
- data/lib/active_support/core_ext/securerandom.rb +57 -0
- data/lib/active_support/core_ext/string/access.rb +93 -56
- data/lib/active_support/core_ext/string/behavior.rb +8 -0
- data/lib/active_support/core_ext/string/conversions.rb +57 -16
- data/lib/active_support/core_ext/string/exclude.rb +13 -0
- data/lib/active_support/core_ext/string/filters.rb +151 -0
- data/lib/active_support/core_ext/string/indent.rb +45 -0
- data/lib/active_support/core_ext/string/inflections.rb +297 -54
- data/lib/active_support/core_ext/string/inquiry.rb +16 -0
- data/lib/active_support/core_ext/string/multibyte.rb +67 -0
- data/lib/active_support/core_ext/string/output_safety.rb +235 -0
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -18
- data/lib/active_support/core_ext/string/strip.rb +27 -0
- data/lib/active_support/core_ext/string/zones.rb +16 -0
- data/lib/active_support/core_ext/string.rb +14 -10
- 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/thread/backtrace/location.rb +7 -0
- data/lib/active_support/core_ext/time/acts_like.rb +10 -0
- data/lib/active_support/core_ext/time/calculations.rb +358 -153
- data/lib/active_support/core_ext/time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/time/conversions.rb +69 -30
- data/lib/active_support/core_ext/time/zones.rb +97 -0
- data/lib/active_support/core_ext/time.rb +6 -6
- data/lib/active_support/core_ext.rb +5 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +243 -0
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/delegation.rb +183 -0
- data/lib/active_support/dependencies/autoload.rb +72 -0
- data/lib/active_support/dependencies/interlock.rb +55 -0
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +84 -222
- data/lib/active_support/deprecation/behaviors.rb +148 -0
- data/lib/active_support/deprecation/constant_accessor.rb +74 -0
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +54 -0
- data/lib/active_support/deprecation/method_wrappers.rb +68 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +189 -0
- data/lib/active_support/deprecation/reporting.rb +162 -0
- data/lib/active_support/deprecation.rb +81 -0
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +112 -0
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +64 -0
- data/lib/active_support/duration.rb +524 -0
- data/lib/active_support/editor.rb +70 -0
- data/lib/active_support/encrypted_configuration.rb +126 -0
- data/lib/active_support/encrypted_file.rb +133 -0
- data/lib/active_support/environment_inquirer.rb +40 -0
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +318 -0
- data/lib/active_support/event_reporter/test_helper.rb +32 -0
- data/lib/active_support/event_reporter.rb +592 -0
- data/lib/active_support/evented_file_update_checker.rb +185 -0
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +110 -0
- data/lib/active_support/execution_wrapper.rb +150 -0
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +166 -0
- data/lib/active_support/fork_tracker.rb +43 -0
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +41 -0
- data/lib/active_support/hash_with_indifferent_access.rb +464 -0
- data/lib/active_support/html_safe_translation.rb +56 -0
- data/lib/active_support/i18n.rb +17 -0
- data/lib/active_support/i18n_railtie.rb +140 -0
- data/lib/active_support/inflections.rb +68 -49
- data/lib/active_support/inflector/inflections.rb +290 -0
- data/lib/active_support/inflector/methods.rb +387 -0
- data/lib/active_support/inflector/transliterate.rb +147 -0
- data/lib/active_support/inflector.rb +7 -164
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +78 -0
- data/lib/active_support/json/encoding.rb +256 -0
- data/lib/active_support/json.rb +4 -0
- data/lib/active_support/key_generator.rb +66 -0
- data/lib/active_support/lazy_load_hooks.rb +107 -0
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +141 -0
- data/lib/active_support/log_subscriber/test_helper.rb +106 -0
- data/lib/active_support/log_subscriber.rb +188 -0
- data/lib/active_support/logger.rb +55 -0
- data/lib/active_support/logger_silence.rb +21 -0
- data/lib/active_support/logger_thread_safe_level.rb +50 -0
- data/lib/active_support/message_encryptor.rb +374 -0
- data/lib/active_support/message_encryptors.rb +193 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +310 -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 +377 -0
- data/lib/active_support/message_verifiers.rb +189 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +146 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotation_coordinator.rb +102 -0
- data/lib/active_support/messages/rotator.rb +69 -0
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +188 -0
- data/lib/active_support/multibyte/unicode.rb +42 -0
- data/lib/active_support/multibyte.rb +27 -0
- data/lib/active_support/notifications/fanout.rb +467 -0
- data/lib/active_support/notifications/instrumenter.rb +240 -0
- data/lib/active_support/notifications.rb +281 -0
- data/lib/active_support/number_helper/number_converter.rb +190 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
- data/lib/active_support/number_helper/rounding_helper.rb +46 -0
- data/lib/active_support/number_helper.rb +479 -0
- data/lib/active_support/option_merger.rb +38 -0
- data/lib/active_support/ordered_hash.rb +50 -0
- data/lib/active_support/ordered_options.rb +141 -25
- data/lib/active_support/parameter_filter.rb +157 -0
- data/lib/active_support/rails.rb +26 -0
- data/lib/active_support/railtie.rb +180 -0
- data/lib/active_support/reloader.rb +138 -0
- data/lib/active_support/rescuable.rb +176 -0
- data/lib/active_support/secure_compare_rotator.rb +58 -0
- data/lib/active_support/security_utils.rb +38 -0
- data/lib/active_support/string_inquirer.rb +35 -0
- data/lib/active_support/structured_event_subscriber.rb +99 -0
- data/lib/active_support/subscriber.rb +141 -0
- data/lib/active_support/syntax_error_proxy.rb +67 -0
- data/lib/active_support/tagged_logging.rb +157 -0
- data/lib/active_support/test_case.rb +365 -0
- data/lib/active_support/testing/assertions.rb +369 -0
- data/lib/active_support/testing/autorun.rb +10 -0
- data/lib/active_support/testing/constant_lookup.rb +51 -0
- data/lib/active_support/testing/constant_stubbing.rb +54 -0
- data/lib/active_support/testing/declarative.rb +28 -0
- data/lib/active_support/testing/deprecation.rb +82 -0
- data/lib/active_support/testing/error_reporter_assertions.rb +124 -0
- data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +121 -0
- data/lib/active_support/testing/method_call_assertions.rb +69 -0
- data/lib/active_support/testing/notification_assertions.rb +92 -0
- data/lib/active_support/testing/parallelization/server.rb +98 -0
- data/lib/active_support/testing/parallelization/worker.rb +107 -0
- data/lib/active_support/testing/parallelization.rb +79 -0
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/setup_and_teardown.rb +57 -0
- data/lib/active_support/testing/stream.rb +41 -0
- data/lib/active_support/testing/tagged_logging.rb +27 -0
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +273 -0
- data/lib/active_support/time.rb +20 -0
- data/lib/active_support/time_with_zone.rb +613 -0
- data/lib/active_support/values/time_zone.rb +599 -158
- data/lib/active_support/version.rb +7 -6
- data/lib/active_support/xml_mini/jdom.rb +175 -0
- data/lib/active_support/xml_mini/libxml.rb +80 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +83 -0
- data/lib/active_support/xml_mini/nokogiri.rb +83 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +86 -0
- data/lib/active_support/xml_mini/rexml.rb +137 -0
- data/lib/active_support/xml_mini.rb +212 -0
- data/lib/active_support.rb +122 -10
- metadata +524 -93
- data/CHANGELOG +0 -283
- data/lib/active_support/binding_of_caller.rb +0 -84
- data/lib/active_support/breakpoint.rb +0 -523
- data/lib/active_support/class_attribute_accessors.rb +0 -57
- data/lib/active_support/class_inheritable_attributes.rb +0 -117
- data/lib/active_support/clean_logger.rb +0 -36
- data/lib/active_support/core_ext/blank.rb +0 -38
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -14
- data/lib/active_support/core_ext/cgi.rb +0 -5
- data/lib/active_support/core_ext/exception.rb +0 -29
- data/lib/active_support/core_ext/integer/even_odd.rb +0 -24
- data/lib/active_support/core_ext/object_and_class.rb +0 -44
- data/lib/active_support/module_attribute_accessors.rb +0 -57
- data/lib/active_support/whiny_nil.rb +0 -38
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
module Multibyte
|
|
5
|
+
module Unicode
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
# The Unicode version that is supported by the implementation
|
|
9
|
+
UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]
|
|
10
|
+
|
|
11
|
+
# Decompose composed characters to the decomposed form.
|
|
12
|
+
def decompose(type, codepoints)
|
|
13
|
+
if type == :compatibility
|
|
14
|
+
codepoints.pack("U*").unicode_normalize(:nfkd).codepoints
|
|
15
|
+
else
|
|
16
|
+
codepoints.pack("U*").unicode_normalize(:nfd).codepoints
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Compose decomposed characters to the composed form.
|
|
21
|
+
def compose(codepoints)
|
|
22
|
+
codepoints.pack("U*").unicode_normalize(:nfc).codepoints
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent
|
|
26
|
+
# resulting in a valid UTF-8 string.
|
|
27
|
+
#
|
|
28
|
+
# Passing +true+ will forcibly tidy all bytes, assuming that the string's
|
|
29
|
+
# encoding is entirely CP1252 or ISO-8859-1.
|
|
30
|
+
def tidy_bytes(string, force = false)
|
|
31
|
+
return string if string.empty? || string.ascii_only?
|
|
32
|
+
return recode_windows1252_chars(string) if force
|
|
33
|
+
string.scrub { |bad| recode_windows1252_chars(bad) }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
def recode_windows1252_chars(string)
|
|
38
|
+
string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport # :nodoc:
|
|
4
|
+
module Multibyte
|
|
5
|
+
autoload :Chars, "active_support/multibyte/chars"
|
|
6
|
+
autoload :Unicode, "active_support/multibyte/unicode"
|
|
7
|
+
|
|
8
|
+
# The proxy class returned when calling mb_chars. You can use this accessor
|
|
9
|
+
# to configure your own proxy class so you can support other encodings. See
|
|
10
|
+
# the ActiveSupport::Multibyte::Chars implementation for an example how to
|
|
11
|
+
# do this.
|
|
12
|
+
#
|
|
13
|
+
# ActiveSupport::Multibyte.proxy_class = CharsForUTF32
|
|
14
|
+
def self.proxy_class=(klass)
|
|
15
|
+
ActiveSupport.deprecator.warn(
|
|
16
|
+
"ActiveSupport::Multibyte.proxy_class= is deprecated and will be removed in Rails 8.2. " \
|
|
17
|
+
"Use normal string methods instead."
|
|
18
|
+
)
|
|
19
|
+
@proxy_class = klass
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns the current proxy class.
|
|
23
|
+
def self.proxy_class
|
|
24
|
+
@proxy_class ||= ActiveSupport::Multibyte::Chars
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "concurrent/map"
|
|
4
|
+
require "active_support/core_ext/object/try"
|
|
5
|
+
|
|
6
|
+
module ActiveSupport
|
|
7
|
+
module Notifications
|
|
8
|
+
class InstrumentationSubscriberError < RuntimeError
|
|
9
|
+
attr_reader :exceptions
|
|
10
|
+
|
|
11
|
+
def initialize(exceptions)
|
|
12
|
+
@exceptions = exceptions
|
|
13
|
+
exception_class_names = exceptions.map { |e| e.class.name }
|
|
14
|
+
super "Exception(s) occurred within instrumentation subscribers: #{exception_class_names.join(', ')}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module FanoutIteration # :nodoc:
|
|
19
|
+
private
|
|
20
|
+
def iterate_guarding_exceptions(collection, &block)
|
|
21
|
+
case collection.size
|
|
22
|
+
when 0
|
|
23
|
+
when 1
|
|
24
|
+
collection.each(&block)
|
|
25
|
+
else
|
|
26
|
+
exceptions = nil
|
|
27
|
+
|
|
28
|
+
collection.each do |s|
|
|
29
|
+
yield s
|
|
30
|
+
rescue Exception => e
|
|
31
|
+
exceptions ||= []
|
|
32
|
+
exceptions << e
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if exceptions
|
|
36
|
+
exceptions = exceptions.flat_map do |exception|
|
|
37
|
+
exception.is_a?(InstrumentationSubscriberError) ? exception.exceptions : [exception]
|
|
38
|
+
end
|
|
39
|
+
if exceptions.size == 1
|
|
40
|
+
raise exceptions.first
|
|
41
|
+
else
|
|
42
|
+
raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
collection
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# This is a default queue implementation that ships with Notifications.
|
|
52
|
+
# It just pushes events to all registered log subscribers.
|
|
53
|
+
#
|
|
54
|
+
# This class is thread safe. All methods are reentrant.
|
|
55
|
+
class Fanout
|
|
56
|
+
def initialize
|
|
57
|
+
@mutex = Mutex.new
|
|
58
|
+
@string_subscribers = Concurrent::Map.new { |h, k| h.compute_if_absent(k) { [] } }
|
|
59
|
+
@other_subscribers = []
|
|
60
|
+
@all_listeners_for = Concurrent::Map.new
|
|
61
|
+
@groups_for = Concurrent::Map.new
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def inspect # :nodoc:
|
|
65
|
+
total_patterns = @string_subscribers.size + @other_subscribers.size
|
|
66
|
+
"#<#{self.class} (#{total_patterns} patterns)>"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
|
|
70
|
+
subscriber = Subscribers.new(pattern, callable || block, monotonic)
|
|
71
|
+
@mutex.synchronize do
|
|
72
|
+
case pattern
|
|
73
|
+
when String
|
|
74
|
+
@string_subscribers[pattern] << subscriber
|
|
75
|
+
clear_cache(pattern)
|
|
76
|
+
when NilClass, Regexp
|
|
77
|
+
@other_subscribers << subscriber
|
|
78
|
+
clear_cache
|
|
79
|
+
else
|
|
80
|
+
raise ArgumentError, "pattern must be specified as a String, Regexp or empty"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
subscriber
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def unsubscribe(subscriber_or_name)
|
|
87
|
+
@mutex.synchronize do
|
|
88
|
+
case subscriber_or_name
|
|
89
|
+
when String
|
|
90
|
+
@string_subscribers[subscriber_or_name].clear
|
|
91
|
+
clear_cache(subscriber_or_name)
|
|
92
|
+
@other_subscribers.each { |sub| sub.unsubscribe!(subscriber_or_name) }
|
|
93
|
+
else
|
|
94
|
+
pattern = subscriber_or_name.try(:pattern)
|
|
95
|
+
if String === pattern
|
|
96
|
+
@string_subscribers[pattern].delete(subscriber_or_name)
|
|
97
|
+
clear_cache(pattern)
|
|
98
|
+
else
|
|
99
|
+
@other_subscribers.delete(subscriber_or_name)
|
|
100
|
+
clear_cache
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def clear_cache(key = nil) # :nodoc:
|
|
107
|
+
if key
|
|
108
|
+
@all_listeners_for.delete(key)
|
|
109
|
+
@groups_for.delete(key)
|
|
110
|
+
else
|
|
111
|
+
@all_listeners_for.clear
|
|
112
|
+
@groups_for.clear
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
class BaseGroup # :nodoc:
|
|
117
|
+
include FanoutIteration
|
|
118
|
+
|
|
119
|
+
def initialize(listeners, name, id, payload)
|
|
120
|
+
@listeners = listeners
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def each(&block)
|
|
124
|
+
iterate_guarding_exceptions(@listeners, &block)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
class BaseTimeGroup < BaseGroup # :nodoc:
|
|
129
|
+
def start(name, id, payload)
|
|
130
|
+
@start_time = now
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def finish(name, id, payload)
|
|
134
|
+
stop_time = now
|
|
135
|
+
each do |listener|
|
|
136
|
+
listener.call(name, @start_time, stop_time, id, payload)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
class MonotonicTimedGroup < BaseTimeGroup # :nodoc:
|
|
142
|
+
private
|
|
143
|
+
def now
|
|
144
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
class TimedGroup < BaseTimeGroup # :nodoc:
|
|
149
|
+
private
|
|
150
|
+
def now
|
|
151
|
+
Time.now
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
class EventedGroup < BaseGroup # :nodoc:
|
|
156
|
+
def start(name, id, payload)
|
|
157
|
+
each do |s|
|
|
158
|
+
s.start(name, id, payload)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def finish(name, id, payload)
|
|
163
|
+
each do |s|
|
|
164
|
+
s.finish(name, id, payload)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
class EventObjectGroup < BaseGroup # :nodoc:
|
|
170
|
+
def start(name, id, payload)
|
|
171
|
+
@event = build_event(name, id, payload)
|
|
172
|
+
@event.start!
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def finish(name, id, payload)
|
|
176
|
+
@event.payload = payload
|
|
177
|
+
@event.finish!
|
|
178
|
+
|
|
179
|
+
each do |s|
|
|
180
|
+
s.call(@event)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
private
|
|
185
|
+
def build_event(name, id, payload)
|
|
186
|
+
ActiveSupport::Notifications::Event.new name, nil, nil, id, payload
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def group_listeners(listeners) # :nodoc:
|
|
191
|
+
listeners.group_by(&:group_class).transform_values do |s|
|
|
192
|
+
s.map(&:delegate).freeze
|
|
193
|
+
end.freeze
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def groups_for(name) # :nodoc:
|
|
197
|
+
silenceable_groups, groups = @groups_for.compute_if_absent(name) do
|
|
198
|
+
listeners = all_listeners_for(name)
|
|
199
|
+
listeners.partition(&:silenceable).map { |l| group_listeners(l) }
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
unless silenceable_groups.empty?
|
|
203
|
+
silenceable_groups.each do |group_class, subscriptions|
|
|
204
|
+
active_subscriptions = subscriptions.reject { |s| s.silenced?(name) }
|
|
205
|
+
unless active_subscriptions.empty?
|
|
206
|
+
groups = groups.dup if groups.frozen?
|
|
207
|
+
base_groups = groups[group_class]
|
|
208
|
+
groups[group_class] = base_groups ? base_groups + active_subscriptions : active_subscriptions
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
groups
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# A +Handle+ is used to record the start and finish time of event.
|
|
217
|
+
#
|
|
218
|
+
# Both #start and #finish must each be called exactly once.
|
|
219
|
+
#
|
|
220
|
+
# Where possible, it's best to use the block form: ActiveSupport::Notifications.instrument.
|
|
221
|
+
# +Handle+ is a low-level API intended for cases where the block form can't be used.
|
|
222
|
+
#
|
|
223
|
+
# handle = ActiveSupport::Notifications.instrumenter.build_handle("my.event", {})
|
|
224
|
+
# begin
|
|
225
|
+
# handle.start
|
|
226
|
+
# # work to be instrumented
|
|
227
|
+
# ensure
|
|
228
|
+
# handle.finish
|
|
229
|
+
# end
|
|
230
|
+
class Handle
|
|
231
|
+
include FanoutIteration
|
|
232
|
+
|
|
233
|
+
def initialize(notifier, name, id, groups, payload) # :nodoc:
|
|
234
|
+
@name = name
|
|
235
|
+
@id = id
|
|
236
|
+
@payload = payload
|
|
237
|
+
@groups = groups
|
|
238
|
+
@state = :initialized
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def start
|
|
242
|
+
ensure_state! :initialized
|
|
243
|
+
@state = :started
|
|
244
|
+
|
|
245
|
+
iterate_guarding_exceptions(@groups) do |group|
|
|
246
|
+
group.start(@name, @id, @payload)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def finish
|
|
251
|
+
finish_with_values(@name, @id, @payload)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def finish_with_values(name, id, payload) # :nodoc:
|
|
255
|
+
ensure_state! :started
|
|
256
|
+
@state = :finished
|
|
257
|
+
|
|
258
|
+
iterate_guarding_exceptions(@groups) do |group|
|
|
259
|
+
group.finish(name, id, payload)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
private
|
|
264
|
+
def ensure_state!(expected)
|
|
265
|
+
if @state != expected
|
|
266
|
+
raise ArgumentError, "expected state to be #{expected.inspect} but was #{@state.inspect}"
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
module NullHandle # :nodoc:
|
|
272
|
+
extend self
|
|
273
|
+
|
|
274
|
+
def start
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def finish
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def finish_with_values(_name, _id, _payload)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
include FanoutIteration
|
|
285
|
+
|
|
286
|
+
def build_handle(name, id, payload)
|
|
287
|
+
groups = groups_for(name).map do |group_klass, grouped_listeners|
|
|
288
|
+
group_klass.new(grouped_listeners, name, id, payload)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
if groups.empty?
|
|
292
|
+
NullHandle
|
|
293
|
+
else
|
|
294
|
+
Handle.new(self, name, id, groups, payload)
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def start(name, id, payload)
|
|
299
|
+
handle_stack = (IsolatedExecutionState[:_fanout_handle_stack] ||= [])
|
|
300
|
+
handle = build_handle(name, id, payload)
|
|
301
|
+
handle_stack << handle
|
|
302
|
+
handle.start
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def finish(name, id, payload, listeners = nil)
|
|
306
|
+
handle_stack = IsolatedExecutionState[:_fanout_handle_stack]
|
|
307
|
+
handle = handle_stack.pop
|
|
308
|
+
handle.finish_with_values(name, id, payload)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def publish(name, ...)
|
|
312
|
+
iterate_guarding_exceptions(listeners_for(name)) { |s| s.publish(name, ...) }
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def publish_event(event)
|
|
316
|
+
iterate_guarding_exceptions(listeners_for(event.name)) { |s| s.publish_event(event) }
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def all_listeners_for(name)
|
|
320
|
+
# this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
|
|
321
|
+
@all_listeners_for[name] || @mutex.synchronize do
|
|
322
|
+
# use synchronisation when accessing @subscribers
|
|
323
|
+
@all_listeners_for[name] ||=
|
|
324
|
+
@string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def listeners_for(name)
|
|
329
|
+
all_listeners_for(name).reject { |s| s.silenced?(name) }
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def listening?(name)
|
|
333
|
+
all_listeners_for(name).any? { |s| !s.silenced?(name) }
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# This is a sync queue, so there is no waiting.
|
|
337
|
+
def wait
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
module Subscribers # :nodoc:
|
|
341
|
+
def self.new(pattern, listener, monotonic)
|
|
342
|
+
subscriber_class = monotonic ? MonotonicTimed : Timed
|
|
343
|
+
|
|
344
|
+
if listener.respond_to?(:start) && listener.respond_to?(:finish)
|
|
345
|
+
subscriber_class = Evented
|
|
346
|
+
else
|
|
347
|
+
# Doing this to detect a single argument block or callable
|
|
348
|
+
# like `proc { |x| }` vs `proc { |*x| }`, `proc { |**x| }`,
|
|
349
|
+
# or `proc { |x, **y| }`
|
|
350
|
+
procish = listener.respond_to?(:parameters) ? listener : listener.method(:call)
|
|
351
|
+
|
|
352
|
+
if procish.arity == 1 && procish.parameters.length == 1
|
|
353
|
+
subscriber_class = EventObject
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
subscriber_class.new(pattern, listener)
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
class Matcher # :nodoc:
|
|
361
|
+
attr_reader :pattern, :exclusions
|
|
362
|
+
|
|
363
|
+
def self.wrap(pattern)
|
|
364
|
+
if String === pattern
|
|
365
|
+
pattern
|
|
366
|
+
elsif pattern.nil?
|
|
367
|
+
AllMessages.new
|
|
368
|
+
else
|
|
369
|
+
new(pattern)
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def initialize(pattern)
|
|
374
|
+
@pattern = pattern
|
|
375
|
+
@exclusions = Set.new
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def unsubscribe!(name)
|
|
379
|
+
exclusions << -name if pattern === name
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def ===(name)
|
|
383
|
+
pattern === name && !exclusions.include?(name)
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
class AllMessages
|
|
387
|
+
def ===(name)
|
|
388
|
+
true
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def unsubscribe!(*)
|
|
392
|
+
false
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
class Evented # :nodoc:
|
|
398
|
+
attr_reader :pattern, :delegate, :silenceable
|
|
399
|
+
|
|
400
|
+
def initialize(pattern, delegate)
|
|
401
|
+
@pattern = Matcher.wrap(pattern)
|
|
402
|
+
@delegate = delegate
|
|
403
|
+
@silenceable = delegate.respond_to?(:silenced?)
|
|
404
|
+
@can_publish = delegate.respond_to?(:publish)
|
|
405
|
+
@can_publish_event = delegate.respond_to?(:publish_event)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def group_class
|
|
409
|
+
EventedGroup
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def publish(...)
|
|
413
|
+
if @can_publish
|
|
414
|
+
@delegate.publish(...)
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def publish_event(event)
|
|
419
|
+
if @can_publish_event
|
|
420
|
+
@delegate.publish_event event
|
|
421
|
+
else
|
|
422
|
+
publish(event.name, event.time, event.end, event.transaction_id, event.payload)
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def silenced?(name)
|
|
427
|
+
@silenceable && @delegate.silenced?(name)
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def subscribed_to?(name)
|
|
431
|
+
pattern === name
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def unsubscribe!(name)
|
|
435
|
+
pattern.unsubscribe!(name)
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
class Timed < Evented # :nodoc:
|
|
440
|
+
def group_class
|
|
441
|
+
TimedGroup
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def publish(...)
|
|
445
|
+
@delegate.call(...)
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
class MonotonicTimed < Timed # :nodoc:
|
|
450
|
+
def group_class
|
|
451
|
+
MonotonicTimedGroup
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
class EventObject < Evented
|
|
456
|
+
def group_class
|
|
457
|
+
EventObjectGroup
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def publish_event(event)
|
|
461
|
+
@delegate.call event
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
end
|