diff --git a/actionview/lib/action_view/helpers/cache_helper.rb b/actionview/lib/action_view/helpers/cache_helper.rb index d149386d14..906b868d80 100644 --- a/actionview/lib/action_view/helpers/cache_helper.rb +++ b/actionview/lib/action_view/helpers/cache_helper.rb @@ -292,19 +292,20 @@ module ActionView controller.write_fragment(name, fragment, options) end - class CachingRegistry - extend ActiveSupport::PerThreadRegistry + module CachingRegistry # :nodoc: + extend self - attr_accessor :caching - alias caching? caching + def caching? + ActiveSupport::IsolatedExecutionState[:action_view_caching] ||= false + end - def self.track_caching - caching_was = self.caching - self.caching = true + def track_caching + caching_was = ActiveSupport::IsolatedExecutionState[:action_view_caching] + ActiveSupport::IsolatedExecutionState[:action_view_caching] = true yield ensure - self.caching = caching_was + ActiveSupport::IsolatedExecutionState[:action_view_caching] = caching_was end end end diff --git a/activerecord/lib/active_record/explain_registry.rb b/activerecord/lib/active_record/explain_registry.rb index 7fd078941a..41950009b4 100644 --- a/activerecord/lib/active_record/explain_registry.rb +++ b/activerecord/lib/active_record/explain_registry.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "active_support/per_thread_registry" +require "active_support/core_ext/module/delegation" module ActiveRecord # This is a thread locals registry for EXPLAIN. For example @@ -8,13 +8,18 @@ module ActiveRecord # ActiveRecord::ExplainRegistry.queries # # returns the collected queries local to the current thread. - # - # See the documentation of ActiveSupport::PerThreadRegistry - # for further details. class ExplainRegistry # :nodoc: - extend ActiveSupport::PerThreadRegistry + class << self + delegate :reset, :collect, :collect=, :collect?, :queries, to: :instance - attr_accessor :queries, :collect + private + def instance + ActiveSupport::IsolatedExecutionState[:active_record_explain_registry] ||= new + end + end + + attr_accessor :collect + attr_reader :queries def initialize reset diff --git a/activerecord/lib/active_record/relation/record_fetch_warning.rb b/activerecord/lib/active_record/relation/record_fetch_warning.rb index 2f20357823..6317eeb485 100644 --- a/activerecord/lib/active_record/relation/record_fetch_warning.rb +++ b/activerecord/lib/active_record/relation/record_fetch_warning.rb @@ -31,17 +31,15 @@ module ActiveRecord end # :startdoc: - class QueryRegistry # :nodoc: - extend ActiveSupport::PerThreadRegistry + module QueryRegistry # :nodoc: + extend self - attr_reader :queries - - def initialize - @queries = [] + def queries + ActiveSupport::IsolatedExecutionState[:active_record_query_registry] ||= [] end def reset - @queries.clear + queries.clear end end end diff --git a/activerecord/lib/active_record/runtime_registry.rb b/activerecord/lib/active_record/runtime_registry.rb index edd77c2b66..30df95f0ae 100644 --- a/activerecord/lib/active_record/runtime_registry.rb +++ b/activerecord/lib/active_record/runtime_registry.rb @@ -1,22 +1,20 @@ # frozen_string_literal: true -require "active_support/per_thread_registry" - module ActiveRecord # This is a thread locals registry for Active Record. For example: # - # ActiveRecord::RuntimeRegistry.connection_handler + # ActiveRecord::RuntimeRegistry.sql_runtime # - # returns the connection handler local to the current thread. - # - # See the documentation of ActiveSupport::PerThreadRegistry - # for further details. - class RuntimeRegistry # :nodoc: - extend ActiveSupport::PerThreadRegistry + # returns the connection handler local to the current unit of execution (either thread of fiber). + module RuntimeRegistry # :nodoc: + extend self - attr_accessor :sql_runtime + def sql_runtime + ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] + end - def self.sql_runtime; instance.sql_runtime; end - def self.sql_runtime=(x); instance.sql_runtime = x; end + def sql_runtime=(runtime) + ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime + end end end diff --git a/activerecord/lib/active_record/scoping.rb b/activerecord/lib/active_record/scoping.rb index 96d3cba49c..353b856aab 100644 --- a/activerecord/lib/active_record/scoping.rb +++ b/activerecord/lib/active_record/scoping.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "active_support/per_thread_registry" +require "active_support/core_ext/module/delegation" module ActiveRecord module Scoping @@ -57,8 +57,8 @@ module ActiveRecord end # This class stores the +:current_scope+ and +:ignore_default_scope+ values - # for different classes. The registry is stored as a thread local, which is - # accessed through +ScopeRegistry.current+. + # for different classes. The registry is stored as either a thread or fiber + # local depending on the application configuration. # # This class allows you to store and get the scope values on different # classes and different types of scopes. For example, if you are attempting @@ -66,22 +66,22 @@ module ActiveRecord # following code: # # registry = ActiveRecord::Scoping::ScopeRegistry - # registry.set_value_for(:current_scope, Board, some_new_scope) + # registry.set_current_scope(Board, some_new_scope) # # Now when you run: # - # registry.value_for(:current_scope, Board) + # registry.current_scope(Board) # - # You will obtain whatever was defined in +some_new_scope+. The #value_for - # and #set_value_for methods are delegated to the current ScopeRegistry - # object, so the above example code can also be called as: - # - # ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope, - # Board, some_new_scope) + # You will obtain whatever was defined in +some_new_scope+. class ScopeRegistry # :nodoc: - extend ActiveSupport::PerThreadRegistry + class << self + delegate :current_scope, :set_current_scope, :ignore_default_scope, :set_ignore_default_scope, + :global_current_scope, :set_global_current_scope, to: :instance - VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope, :global_current_scope] + def instance + ActiveSupport::IsolatedExecutionState[:active_record_scope_registry] ||= new + end + end def initialize @current_scope = {} @@ -89,16 +89,28 @@ module ActiveRecord @global_current_scope = {} end - VALID_SCOPE_TYPES.each do |type| - class_eval <<-eorb, __FILE__, __LINE__ - def #{type}(model, skip_inherited_scope = false) - value_for(@#{type}, model, skip_inherited_scope) - end + def current_scope(model, skip_inherited_scope = false) + value_for(@current_scope, model, skip_inherited_scope) + end - def set_#{type}(model, value) - set_value_for(@#{type}, model, value) - end - eorb + def set_current_scope(model, value) + set_value_for(@current_scope, model, value) + end + + def ignore_default_scope(model, skip_inherited_scope = false) + value_for(@ignore_default_scope, model, skip_inherited_scope) + end + + def set_ignore_default_scope(model, value) + set_value_for(@ignore_default_scope, model, value) + end + + def global_current_scope(model, skip_inherited_scope = false) + value_for(@global_current_scope, model, skip_inherited_scope) + end + + def set_global_current_scope(model, value) + set_value_for(@global_current_scope, model, value) end private diff --git a/activerecord/lib/active_record/suppressor.rb b/activerecord/lib/active_record/suppressor.rb index 49cce16dc8..df5c08dd15 100644 --- a/activerecord/lib/active_record/suppressor.rb +++ b/activerecord/lib/active_record/suppressor.rb @@ -30,32 +30,28 @@ module ActiveRecord module Suppressor extend ActiveSupport::Concern + class << self + def registry # :nodoc: + ActiveSupport::IsolatedExecutionState[:active_record_suppresor_registry] ||= {} + end + end + module ClassMethods def suppress(&block) - previous_state = SuppressorRegistry.suppressed[name] - SuppressorRegistry.suppressed[name] = true + previous_state = Suppressor.registry[name] + Suppressor.registry[name] = true yield ensure - SuppressorRegistry.suppressed[name] = previous_state + Suppressor.registry[name] = previous_state end end def save(**) # :nodoc: - SuppressorRegistry.suppressed[self.class.name] ? true : super + Suppressor.registry[self.class.name] ? true : super end def save!(**) # :nodoc: - SuppressorRegistry.suppressed[self.class.name] ? true : super - end - end - - class SuppressorRegistry # :nodoc: - extend ActiveSupport::PerThreadRegistry - - attr_reader :suppressed - - def initialize - @suppressed = {} + Suppressor.registry[self.class.name] ? true : super end end end diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 984e0bb67b..48ecc96e4b 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -51,6 +51,7 @@ module ActiveSupport autoload :IsolatedExecutionState autoload :Notifications autoload :Reloader + autoload :PerThreadRegistry autoload :SecureCompareRotator eager_autoload do diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb index 20b08e494e..0b2e0d7868 100644 --- a/activesupport/lib/active_support/cache/strategy/local_cache.rb +++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "active_support/core_ext/string/inflections" -require "active_support/per_thread_registry" module ActiveSupport module Cache @@ -13,23 +12,18 @@ module ActiveSupport autoload :Middleware, "active_support/cache/strategy/local_cache_middleware" # Class for storing and registering the local caches. - class LocalCacheRegistry # :nodoc: - extend ActiveSupport::PerThreadRegistry - - def initialize - @registry = {} - end + module LocalCacheRegistry # :nodoc: + extend self def cache_for(local_cache_key) - @registry[local_cache_key] + registry = ActiveSupport::IsolatedExecutionState[:active_support_local_cache_registry] ||= {} + registry[local_cache_key] end def set_cache_for(local_cache_key, value) - @registry[local_cache_key] = value + registry = ActiveSupport::IsolatedExecutionState[:active_support_local_cache_registry] ||= {} + registry[local_cache_key] = value end - - def self.set_cache_for(l, v); instance.set_cache_for l, v; end - def self.cache_for(l); instance.cache_for l; end end # Simple memory backed cache. This cache is not thread safe and is intended only diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index e8f838db38..c7986b83ea 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -2,7 +2,6 @@ require "active_support/notifications/instrumenter" require "active_support/notifications/fanout" -require "active_support/per_thread_registry" module ActiveSupport # = Notifications @@ -261,28 +260,13 @@ module ActiveSupport end def instrumenter - InstrumentationRegistry.instance.instrumenter_for(notifier) - end - end - - # This class is a registry which holds all of the +Instrumenter+ objects - # in a particular thread local. To access the +Instrumenter+ object for a - # particular +notifier+, you can call the following method: - # - # InstrumentationRegistry.instrumenter_for(notifier) - # - # The instrumenters for multiple notifiers are held in a single instance of - # this class. - class InstrumentationRegistry # :nodoc: - extend ActiveSupport::PerThreadRegistry - - def initialize - @registry = {} + registry[notifier] ||= Instrumenter.new(notifier) end - def instrumenter_for(notifier) - @registry[notifier] ||= Instrumenter.new(notifier) - end + private + def registry + ActiveSupport::IsolatedExecutionState[:active_support_notifications_registry] ||= {} + end end self.notifier = Fanout.new diff --git a/activesupport/lib/active_support/per_thread_registry.rb b/activesupport/lib/active_support/per_thread_registry.rb index 3f961b0f4c..cd8db9114a 100644 --- a/activesupport/lib/active_support/per_thread_registry.rb +++ b/activesupport/lib/active_support/per_thread_registry.rb @@ -40,6 +40,10 @@ module ActiveSupport # If the class has an initializer, it must accept no arguments. module PerThreadRegistry def self.extended(object) + ActiveSupport::Deprecation.warn(<<~MSG) + ActiveSupport::PerThreadRegistry is deprecated and will be removed in Rails 7.1. + Use `Module#thread_mattr_accessor` instead. + MSG object.instance_variable_set :@per_thread_registry_key, object.name.freeze end diff --git a/activesupport/lib/active_support/subscriber.rb b/activesupport/lib/active_support/subscriber.rb index 991c5d8d30..0f71443e42 100644 --- a/activesupport/lib/active_support/subscriber.rb +++ b/activesupport/lib/active_support/subscriber.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "active_support/per_thread_registry" require "active_support/notifications" module ActiveSupport @@ -157,23 +156,8 @@ module ActiveSupport private def event_stack - SubscriberQueueRegistry.instance.get_queue(@queue_key) + registry = ActiveSupport::IsolatedExecutionState[:active_support_subscriber_queue_registry] ||= {} + registry[@queue_key] ||= [] end end - - # This is a registry for all the event stacks kept for subscribers. - # - # See the documentation of ActiveSupport::PerThreadRegistry - # for further details. - class SubscriberQueueRegistry # :nodoc: - extend PerThreadRegistry - - def initialize - @registry = {} - end - - def get_queue(queue_key) - @registry[queue_key] ||= [] - end - end end diff --git a/activesupport/test/per_thread_registry_test.rb b/activesupport/test/per_thread_registry_test.rb index b0e46f88ca..67fbaa1916 100644 --- a/activesupport/test/per_thread_registry_test.rb +++ b/activesupport/test/per_thread_registry_test.rb @@ -4,7 +4,9 @@ require_relative "abstract_unit" class PerThreadRegistryTest < ActiveSupport::TestCase class TestRegistry - extend ActiveSupport::PerThreadRegistry + ActiveSupport::Deprecation.silence do + extend ActiveSupport::PerThreadRegistry + end def foo(x:); x; end end