From 18e7406975ee9b1cd3790a03142b7681f826e4ee Mon Sep 17 00:00:00 2001 From: masato_hi Date: Thu, 3 Jun 2021 12:07:54 +0900 Subject: [PATCH 1/6] Support Rails 6 multiple db connections. --- .../refresh_connection_management.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb index d4abbaf..ff7852a 100644 --- a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb +++ b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb @@ -30,10 +30,22 @@ def call(env) private def clear_connections - if should_clear_all_connections? - ActiveRecord::Base.clear_all_connections! + if ActiveRecord::VERSION::MAJOR >= 6 + if should_clear_all_connections? + ActiveRecord::Base.connection_handlers.each_value do |connection_handler| + connection_handler.clear_all_connections! + end + else + ActiveRecord::Base.connection_handlers.each_value do |connection_handler| + connection_handler.clear_active_connections! + end + end else - ActiveRecord::Base.clear_active_connections! + if should_clear_all_connections? + ActiveRecord::Base.clear_all_connections! + else + ActiveRecord::Base.clear_active_connections! + end end end From b77c43cc5a3a7380d6da02bcdb4195222def0cd4 Mon Sep 17 00:00:00 2001 From: masato_hi Date: Fri, 4 Jun 2021 13:58:28 +0900 Subject: [PATCH 2/6] Fixed an error when legacy_connection_handling is false. --- .../refresh_connection_management.rb | 69 +++++++++++++++---- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb index ff7852a..026078e 100644 --- a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb +++ b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb @@ -2,11 +2,14 @@ module ActiveRecord module ConnectionAdapters class RefreshConnectionManagement DEFAULT_OPTIONS = {max_requests: 1} + AR_VERSION_6_1 = "6.1".freeze + AR_VERSION_6_0 = "6.0".freeze def initialize(app, options = {}) @app = app @options = DEFAULT_OPTIONS.merge(options) @mutex = Mutex.new + @ar_version = ActiveRecord.gem_version.to_s reset_remain_count end @@ -30,22 +33,64 @@ def call(env) private def clear_connections - if ActiveRecord::VERSION::MAJOR >= 6 - if should_clear_all_connections? - ActiveRecord::Base.connection_handlers.each_value do |connection_handler| - connection_handler.clear_all_connections! - end + if @ar_version >= AR_VERSION_6_1 + if legacy_connection_handling? + clear_legacy_compatible_connections else - ActiveRecord::Base.connection_handlers.each_value do |connection_handler| - connection_handler.clear_active_connections! - end + clear_all_roles_connections end + elsif @ar_version >= AR_VERSION_6_0 + clear_legacy_compatible_connections else - if should_clear_all_connections? - ActiveRecord::Base.clear_all_connections! - else - ActiveRecord::Base.clear_active_connections! + clear_legacy_connections + end + end + + def legacy_connection_handling? + begin + ActiveRecord::Base.legacy_connection_handling + rescue NoMethodError + false + end + end + + def all_roles + roles = [] + ActiveRecord::Base.connection_handler.instance_variable_get(:@owner_to_pool_manager).each_value do |pool_manager| + roles.concat(pool_manager.role_names) + end + roles.uniq + end + + def clear_all_roles_connections + if should_clear_all_connections? + all_roles.each do |role| + ActiveRecord::Base.clear_all_connections!(role) + end + else + all_roles.each do |role| + ActiveRecord::Base.clear_active_connections!(role) + end + end + end + + def clear_legacy_compatible_connections + if should_clear_all_connections? + ActiveRecord::Base.connection_handlers.each_value do |connection_handler| + connection_handler.clear_all_connections! end + else + ActiveRecord::Base.connection_handlers.each_value do |connection_handler| + connection_handler.clear_active_connections! + end + end + end + + def clear_legacy_connections + if should_clear_all_connections? + ActiveRecord::Base.clear_all_connections! + else + ActiveRecord::Base.clear_active_connections! end end From fa792c963e00cf48093310c53746735a74dc8835 Mon Sep 17 00:00:00 2001 From: masato_hi Date: Fri, 4 Jun 2021 17:23:24 +0900 Subject: [PATCH 3/6] Fix disconnection process in Rails 6.1 --- .../refresh_connection_management.rb | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb index 026078e..34a01e3 100644 --- a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb +++ b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb @@ -37,7 +37,7 @@ def clear_connections if legacy_connection_handling? clear_legacy_compatible_connections else - clear_all_roles_connections + clear_multi_db_connections end elsif @ar_version >= AR_VERSION_6_0 clear_legacy_compatible_connections @@ -54,22 +54,14 @@ def legacy_connection_handling? end end - def all_roles - roles = [] - ActiveRecord::Base.connection_handler.instance_variable_get(:@owner_to_pool_manager).each_value do |pool_manager| - roles.concat(pool_manager.role_names) - end - roles.uniq - end - - def clear_all_roles_connections + def clear_multi_db_connections if should_clear_all_connections? - all_roles.each do |role| - ActiveRecord::Base.clear_all_connections!(role) + ActiveRecord::Base.connection_handler.all_connection_pools.each do |pool| + pool.disconnect! end else - all_roles.each do |role| - ActiveRecord::Base.clear_active_connections!(role) + ActiveRecord::Base.connection_handler.all_connection_pools.each do |pool| + pool.release_connection if pool.active_connection? && !pool.connection.transaction_open? end end end From 0ece604aaba3f085e90efafe9b8cd2488263e8b9 Mon Sep 17 00:00:00 2001 From: masato_hi Date: Fri, 4 Jun 2021 18:58:39 +0900 Subject: [PATCH 4/6] Performance improvements and removal of branching of processing by legacy handlers. --- .../refresh_connection_management.rb | 45 +++++++------------ 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb index 34a01e3..1b978f7 100644 --- a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb +++ b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb @@ -2,15 +2,13 @@ module ActiveRecord module ConnectionAdapters class RefreshConnectionManagement DEFAULT_OPTIONS = {max_requests: 1} - AR_VERSION_6_1 = "6.1".freeze - AR_VERSION_6_0 = "6.0".freeze def initialize(app, options = {}) @app = app @options = DEFAULT_OPTIONS.merge(options) @mutex = Mutex.new - @ar_version = ActiveRecord.gem_version.to_s + resolve_clear_connections reset_remain_count end @@ -33,32 +31,25 @@ def call(env) private def clear_connections - if @ar_version >= AR_VERSION_6_1 - if legacy_connection_handling? - clear_legacy_compatible_connections - else - clear_multi_db_connections - end - elsif @ar_version >= AR_VERSION_6_0 - clear_legacy_compatible_connections - else - clear_legacy_connections - end + __send__(@clear_connections) end - def legacy_connection_handling? - begin - ActiveRecord::Base.legacy_connection_handling - rescue NoMethodError - false - end + def resolve_clear_connections + ar_version = ActiveRecord.gem_version.to_s + + @clear_connections = + if ar_version >= "6.1" + :clear_multi_db_connections + elsif ar_version >= "6.0" + :clear_legacy_compatible_connections + else + :clear_legacy_connections + end end def clear_multi_db_connections if should_clear_all_connections? - ActiveRecord::Base.connection_handler.all_connection_pools.each do |pool| - pool.disconnect! - end + ActiveRecord::Base.connection_handler.all_connection_pools.each(&:disconnect!) else ActiveRecord::Base.connection_handler.all_connection_pools.each do |pool| pool.release_connection if pool.active_connection? && !pool.connection.transaction_open? @@ -68,13 +59,9 @@ def clear_multi_db_connections def clear_legacy_compatible_connections if should_clear_all_connections? - ActiveRecord::Base.connection_handlers.each_value do |connection_handler| - connection_handler.clear_all_connections! - end + ActiveRecord::Base.connection_handlers.each_value(&:clear_all_connections!) else - ActiveRecord::Base.connection_handlers.each_value do |connection_handler| - connection_handler.clear_active_connections! - end + ActiveRecord::Base.connection_handlers.each_value(&:clear_active_connections!) end end From 10de61c4827e5116683983b8080f63ed8549fcdd Mon Sep 17 00:00:00 2001 From: masato_hi Date: Fri, 4 Jun 2021 22:11:32 +0900 Subject: [PATCH 5/6] Fixed processing when legacy_connection_handling is true. --- .../refresh_connection_management.rb | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb index 1b978f7..5767cc4 100644 --- a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb +++ b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb @@ -39,9 +39,13 @@ def resolve_clear_connections @clear_connections = if ar_version >= "6.1" - :clear_multi_db_connections + if ActiveRecord::Base.legacy_connection_handling + :clear_legacy_compatible_connections + else + :clear_multi_db_connections + end elsif ar_version >= "6.0" - :clear_legacy_compatible_connections + :clear_ar_6_0_connections else :clear_legacy_connections end @@ -58,6 +62,20 @@ def clear_multi_db_connections end def clear_legacy_compatible_connections + if should_clear_all_connections? + ActiveRecord::Base.connection_handlers.each_value do |handler| + handler.connection_pool_list.each(&:disconnect!) + end + else + ActiveRecord::Base.connection_handlers.each_value do |handler| + handler.connection_pool_list.each do |pool| + pool.release_connection if pool.active_connection? && !pool.connection.transaction_open? + end + end + end + end + + def clear_ar_6_0_connections if should_clear_all_connections? ActiveRecord::Base.connection_handlers.each_value(&:clear_all_connections!) else From c15b57fa95e6bd19177edc0042f4c101de352cf8 Mon Sep 17 00:00:00 2001 From: masato_hi Date: Mon, 7 Jun 2021 14:32:13 +0900 Subject: [PATCH 6/6] Fix ActiveRecord::Base.connection_handler to disconnect when legacy_connection_handling is true. --- .../connection_adapters/refresh_connection_management.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb index 5767cc4..3ae3ef3 100644 --- a/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb +++ b/lib/activerecord-refresh_connection/active_record/connection_adapters/refresh_connection_management.rb @@ -66,12 +66,14 @@ def clear_legacy_compatible_connections ActiveRecord::Base.connection_handlers.each_value do |handler| handler.connection_pool_list.each(&:disconnect!) end + ActiveRecord::Base.clear_all_connections! else ActiveRecord::Base.connection_handlers.each_value do |handler| handler.connection_pool_list.each do |pool| pool.release_connection if pool.active_connection? && !pool.connection.transaction_open? end end + ActiveRecord::Base.clear_active_connections! end end