From 703baa66c1c8ac7e1712fca7399161595fb8739a Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Fri, 19 Nov 2021 11:54:11 +0100 Subject: [PATCH] Use `IsolatedExecutionState` across Active Record Ref: https://github.com/rails/rails/pull/43596 This allow users to declare wether their unit of work is isolated by fibers or by threads. --- .../abstract/connection_handler.rb | 4 ++-- .../connection_adapters/abstract_adapter.rb | 2 +- .../sqlite3/database_statements.rb | 4 ++-- .../lib/active_record/connection_handling.rb | 10 ++++------ activerecord/lib/active_record/core.rb | 12 ++++++------ activerecord/lib/active_record/no_touching.rb | 2 +- 6 files changed, 16 insertions(+), 18 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb index 04a67ae23a..bab5e2a08d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb @@ -81,11 +81,11 @@ module ActiveRecord end def prevent_writes # :nodoc: - Thread.current[:prevent_writes] + ActiveSupport::IsolatedExecutionState[:active_record_prevent_writes] end def prevent_writes=(prevent_writes) # :nodoc: - Thread.current[:prevent_writes] = prevent_writes + ActiveSupport::IsolatedExecutionState[:active_record_prevent_writes] = prevent_writes end # Prevent writing to the database regardless of role. diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index bce336c14c..48c7a0fa9d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -178,7 +178,7 @@ module ActiveRecord alias :prepared_statements :prepared_statements? def prepared_statements_disabled_cache # :nodoc: - Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new + ActiveSupport::IsolatedExecutionState[:active_record_prepared_statements_disabled_cache] ||= Set.new end class Version diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb index 85329fd4b8..4d970313d1 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb @@ -78,7 +78,7 @@ module ActiveRecord raise TransactionIsolationError, "SQLite3 only supports the `read_uncommitted` transaction isolation level" if isolation != :read_uncommitted raise StandardError, "You need to enable the shared-cache mode in SQLite mode before attempting to change the transaction isolation level" unless shared_cache? - Thread.current.thread_variable_set("read_uncommitted", @connection.get_first_value("PRAGMA read_uncommitted")) + ActiveSupport::IsolatedExecutionState[:active_record_read_uncommitted] = @connection.get_first_value("PRAGMA read_uncommitted") @connection.read_uncommitted = true begin_db_transaction end @@ -108,7 +108,7 @@ module ActiveRecord private def reset_read_uncommitted - read_uncommitted = Thread.current.thread_variable_get("read_uncommitted") + read_uncommitted = ActiveSupport::IsolatedExecutionState[:active_record_read_uncommitted] return unless read_uncommitted @connection.read_uncommitted = read_uncommitted diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb index 65c029cbe2..2ea8e0c1d8 100644 --- a/activerecord/lib/active_record/connection_handling.rb +++ b/activerecord/lib/active_record/connection_handling.rb @@ -212,18 +212,16 @@ module ActiveRecord # is useful in cases you're using sharding to provide per-request # database isolation. def prohibit_shard_swapping(enabled = true) - prev_value = Thread.current.thread_variable_get(:prohibit_shard_swapping) - - Thread.current.thread_variable_set(:prohibit_shard_swapping, enabled) - + prev_value = ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] + ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = enabled yield ensure - Thread.current.thread_variable_set(:prohibit_shard_swapping, prev_value) + ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = prev_value end # Determine whether or not shard swapping is currently prohibited def shard_swapping_prohibited? - Thread.current.thread_variable_get(:prohibit_shard_swapping) + ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] end # Prevent writing to the database regardless of role. diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 1dfb000220..d8b4693067 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -92,11 +92,11 @@ module ActiveRecord self.filter_attributes = [] def self.connection_handler - Thread.current.thread_variable_get(:ar_connection_handler) || default_connection_handler + ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] || default_connection_handler end def self.connection_handler=(handler) - Thread.current.thread_variable_set(:ar_connection_handler, handler) + ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler end def self.connection_handlers @@ -131,8 +131,8 @@ module ActiveRecord end def self.asynchronous_queries_tracker # :nodoc: - Thread.current.thread_variable_get(:ar_asynchronous_queries_tracker) || - Thread.current.thread_variable_set(:ar_asynchronous_queries_tracker, AsynchronousQueriesTracker.new) + ActiveSupport::IsolatedExecutionState[:active_record_asynchronous_queries_tracker] ||= \ + AsynchronousQueriesTracker.new end # Returns the symbol representing the current connected role. @@ -199,11 +199,11 @@ module ActiveRecord end def self.connected_to_stack # :nodoc: - if connected_to_stack = Thread.current.thread_variable_get(:ar_connected_to_stack) + if connected_to_stack = ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack] connected_to_stack else connected_to_stack = Concurrent::Array.new - Thread.current.thread_variable_set(:ar_connected_to_stack, connected_to_stack) + ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack] = connected_to_stack connected_to_stack end end diff --git a/activerecord/lib/active_record/no_touching.rb b/activerecord/lib/active_record/no_touching.rb index c4e0da1ab4..d0834691bf 100644 --- a/activerecord/lib/active_record/no_touching.rb +++ b/activerecord/lib/active_record/no_touching.rb @@ -39,7 +39,7 @@ module ActiveRecord private def klasses - Thread.current[:no_touching_classes] ||= [] + ActiveSupport::IsolatedExecutionState[:active_record_no_touching_classes] ||= [] end end