From 801053101c80724299afe7a5d7206d13beee0215 Mon Sep 17 00:00:00 2001 From: meganemura Date: Thu, 20 Jul 2017 01:26:26 +0900 Subject: [PATCH 01/22] Removed task dependency --- lib/tasks/apartment.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/apartment.rake b/lib/tasks/apartment.rake index a4187594..a5e9c87f 100644 --- a/lib/tasks/apartment.rake +++ b/lib/tasks/apartment.rake @@ -3,7 +3,7 @@ require 'apartment/migrator' apartment_namespace = namespace :apartment do desc "Create all tenants" - task create: 'db:migrate' do + task :create do tenants.each do |tenant| begin quietly { Apartment::Tenant.create(tenant) } From 676fb9865d98718f701f43f0f034561edc6e8263 Mon Sep 17 00:00:00 2001 From: Alex Pooley Date: Tue, 21 Feb 2017 18:55:19 -0500 Subject: [PATCH 02/22] Kernel#quietly was deprecated in Rails 4.2 --- lib/tasks/apartment.rake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tasks/apartment.rake b/lib/tasks/apartment.rake index a5e9c87f..c1bcee43 100644 --- a/lib/tasks/apartment.rake +++ b/lib/tasks/apartment.rake @@ -6,7 +6,8 @@ apartment_namespace = namespace :apartment do task :create do tenants.each do |tenant| begin - quietly { Apartment::Tenant.create(tenant) } + puts("Creating #{tenant} tenant") + Apartment::Tenant.create(tenant) rescue Apartment::TenantExists => e puts e.message end From c6a221c7f5de90cfcdfce21d2f0b29af59307880 Mon Sep 17 00:00:00 2001 From: Yuki Masutomi Date: Wed, 20 Sep 2017 20:28:11 +0900 Subject: [PATCH 03/22] enhance db:drop task --- lib/apartment/tasks/enhancements.rb | 51 ++++++++++++++++++++--------- lib/tasks/apartment.rake | 12 +++++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/lib/apartment/tasks/enhancements.rb b/lib/apartment/tasks/enhancements.rb index f93b359e..ce93e58a 100644 --- a/lib/apartment/tasks/enhancements.rb +++ b/lib/apartment/tasks/enhancements.rb @@ -3,33 +3,54 @@ module Apartment class RakeTaskEnhancer - - TASKS = %w(db:migrate db:rollback db:migrate:up db:migrate:down db:migrate:redo db:seed) - + + module TASKS + ENHANCE_BEFORE = %w(db:drop) + ENHANCE_AFTER = %w(db:migrate db:rollback db:migrate:up db:migrate:down db:migrate:redo db:seed) + freeze + end + # This is a bit convoluted, but helps solve problems when using Apartment within an engine # See spec/integration/use_within_an_engine.rb - + class << self def enhance! - TASKS.each do |name| + return unless should_enhance? + + # insert task before + TASKS::ENHANCE_BEFORE.each do |name| task = Rake::Task[name] - task.enhance do - if should_enhance? - enhance_task(task) - end - end + enhance_before_task(task) end + + # insert task after + TASKS::ENHANCE_AFTER.each do |name| + task = Rake::Task[name] + enhance_after_task(task) + end + end - + def should_enhance? Apartment.db_migrate_tenants end - - def enhance_task(task) - Rake::Task[task.name.sub(/db:/, 'apartment:')].invoke + + def enhance_before_task(task) + task.enhance([inserted_task_name(task)]) + end + + def enhance_after_task(task) + task.enhance do + Rake::Task[inserted_task_name(task)].invoke + end end + + def inserted_task_name(task) + task.name.sub(/db:/, 'apartment:') + end + end - + end end diff --git a/lib/tasks/apartment.rake b/lib/tasks/apartment.rake index c1bcee43..f51fa4e9 100644 --- a/lib/tasks/apartment.rake +++ b/lib/tasks/apartment.rake @@ -14,6 +14,18 @@ apartment_namespace = namespace :apartment do end end + desc "Drop all tenants" + task :drop do + tenants.each do |tenant| + begin + puts("Dropping #{tenant} tenant") + Apartment::Tenant.drop(tenant) + rescue Apartment::TenantNotFound => e + puts e.message + end + end + end + desc "Migrate all tenants" task :migrate do warn_if_tenants_empty From 8d89b8264978f2e34db2d170f97ff7dc9d7e5120 Mon Sep 17 00:00:00 2001 From: Ingus Skaistkalns Date: Wed, 14 Feb 2018 10:26:10 +0200 Subject: [PATCH 04/22] Support ActiveRecord-5.2 migration context --- lib/apartment/migrator.rb | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/apartment/migrator.rb b/lib/apartment/migrator.rb index 3d14f342..d8a04047 100644 --- a/lib/apartment/migrator.rb +++ b/lib/apartment/migrator.rb @@ -10,8 +10,12 @@ def migrate(database) Tenant.switch(database) do version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, version) do |migration| - ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope) + migration_scope_block = -> (migration) { ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope) } + + if activerecord_below_5_2? + ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, version, &migration_scope_block) + else + ActiveRecord::Base.connection.migration_context.migrate(version, &migration_scope_block) end end end @@ -19,15 +23,29 @@ def migrate(database) # Migrate up/down to a specific version def run(direction, database, version) Tenant.switch(database) do - ActiveRecord::Migrator.run(direction, ActiveRecord::Migrator.migrations_paths, version) + if activerecord_below_5_2? + ActiveRecord::Migrator.run(direction, ActiveRecord::Migrator.migrations_paths, version) + else + ActiveRecord::Base.connection.migration_context.run(direction, version) + end end end # rollback latest migration `step` number of times def rollback(database, step = 1) Tenant.switch(database) do - ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step) + if activerecord_below_5_2? + ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step) + else + ActiveRecord::Base.connection.migration_context.rollback(step) + end end end + + private + + def activerecord_below_5_2? + ActiveRecord.version.release() < Gem::Version.new('5.2.0') + end end end From e28e8708c33661c14e4dd61a2868c903d96155d9 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Mon, 11 Mar 2019 23:01:23 -0400 Subject: [PATCH 05/22] Call drop database for postgres --- lib/apartment/adapters/postgresql_adapter.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/apartment/adapters/postgresql_adapter.rb b/lib/apartment/adapters/postgresql_adapter.rb index 48edb72c..c25f8ede 100644 --- a/lib/apartment/adapters/postgresql_adapter.rb +++ b/lib/apartment/adapters/postgresql_adapter.rb @@ -4,12 +4,9 @@ module Apartment module Adapters class PostgresqlAdapter < AbstractAdapter - # -- ABSTRACT OVERRIDES -- def drop(tenant) - raise NotImplementedError, - "Please use either drop_database or drop_schema for PG adapter" + drop_database(tenant) end - # -- END ABSTRACT OVERRIDES -- def drop_database(tenant) # Apartment.connection.select_all "select pg_terminate_backend(pg_stat_activity.pid) from pg_stat_activity where datname='#{tenant}' AND state='idle';" From 63c8b0673676e25ff08934a16e75a11adc55d317 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Tue, 12 Mar 2019 13:20:36 -0400 Subject: [PATCH 06/22] No longer set default tenant to a hash --- lib/apartment.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/apartment.rb b/lib/apartment.rb index a227fb7f..52b94faa 100644 --- a/lib/apartment.rb +++ b/lib/apartment.rb @@ -10,12 +10,12 @@ class << self ACCESSOR_METHODS = [ :use_sql, :seed_after_create, :tenant_decorator, - :force_reconnect_on_switch, :pool_per_config + :force_reconnect_on_switch, :pool_per_config, :default_tenant ] WRITER_METHODS = [ :tenant_names, :database_schema_file, :excluded_models, :persistent_schemas, :connection_class, :tld_length, :db_migrate_tenants, - :seed_data_file, :default_tenant + :seed_data_file ] OTHER_METHODS = [:tenant_resolver, :resolver_class] @@ -59,10 +59,6 @@ def excluded_models @excluded_models || [] end - def default_tenant - @default_tenant || tenant_resolver.init_config - end - def persistent_schemas @persistent_schemas || [] end From f13b203f1a999c257571594bb333be36ccc5848d Mon Sep 17 00:00:00 2001 From: meganemura Date: Sat, 14 Apr 2018 01:05:46 +0900 Subject: [PATCH 07/22] Use guard clause --- lib/apartment/railtie.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/apartment/railtie.rb b/lib/apartment/railtie.rb index 465c40f9..59497257 100644 --- a/lib/apartment/railtie.rb +++ b/lib/apartment/railtie.rb @@ -28,9 +28,13 @@ def self.prep # See the middleware/console declarations below to help with this. Hope to fix that soon. # config.to_prepare do - unless ARGV.any? { |arg| arg =~ /\Aassets:(?:precompile|clean)\z/ } + next if ARGV.any? { |arg| arg =~ /\Aassets:(?:precompile|clean)\z/ } + + begin Apartment::Tenant.init Apartment.connection_class.clear_active_connections! + rescue ::ActiveRecord::NoDatabaseError => e + puts e.message end end From 29af321d296424322132f2525baea04de483d29c Mon Sep 17 00:00:00 2001 From: meganemura Date: Sat, 14 Apr 2018 01:10:16 +0900 Subject: [PATCH 08/22] Swallow the AR::NoDatabaseError Printing an Error message is a little bit annoying until invoke db:create. # Conflicts: # lib/apartment/railtie.rb --- lib/apartment/railtie.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/apartment/railtie.rb b/lib/apartment/railtie.rb index 59497257..ba11452a 100644 --- a/lib/apartment/railtie.rb +++ b/lib/apartment/railtie.rb @@ -33,8 +33,9 @@ def self.prep begin Apartment::Tenant.init Apartment.connection_class.clear_active_connections! - rescue ::ActiveRecord::NoDatabaseError => e - puts e.message + rescue ::ActiveRecord::NoDatabaseError + # Since `db:create` and other tasks invoke this block from Rails 5.2.0, + # we need to swallow the error to execute `db:create` properly. end end From 92359d8fbf42f87c098c730640774b942c1be035 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Tue, 12 Mar 2019 13:29:00 -0400 Subject: [PATCH 09/22] Fix calls to connection_switch! method --- lib/apartment/adapters/abstract_adapter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/apartment/adapters/abstract_adapter.rb b/lib/apartment/adapters/abstract_adapter.rb index 29e4988c..f8acea2a 100644 --- a/lib/apartment/adapters/abstract_adapter.rb +++ b/lib/apartment/adapters/abstract_adapter.rb @@ -31,7 +31,7 @@ def create(tenant) difference = current_difference_from(config) if difference[:host] - connection_switch(config, without_keys: [:database, :schema_search_path]) + connection_switch!(config, without_keys: [:database, :schema_search_path]) end create_tenant!(config) @@ -55,7 +55,7 @@ def drop(tenant) difference = current_difference_from(config) if difference[:host] - connection_switch(config, without_keys: [:database]) + connection_switch!(config, without_keys: [:database]) end unless database_exists?(config[:database]) From 18cdf105d90cd67767e6f0685535e9e07fb1cab8 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Tue, 12 Mar 2019 13:31:10 -0400 Subject: [PATCH 10/22] Always use postgresql adapter --- lib/apartment/tenant.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/apartment/tenant.rb b/lib/apartment/tenant.rb index d6ed3350..6436171b 100644 --- a/lib/apartment/tenant.rb +++ b/lib/apartment/tenant.rb @@ -25,9 +25,7 @@ def init # def adapter Thread.current[:apartment_adapter] ||= begin - config = Apartment.default_tenant - - adapter_name = "#{config[:adapter]}_adapter" + adapter_name = "postgresql_adapter" begin require "apartment/adapters/#{adapter_name}" From 698b6888ba51c773f7049cfccab1181ebfe31648 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Tue, 12 Mar 2019 13:33:12 -0400 Subject: [PATCH 11/22] Rescue from expected errors when dropping a database --- lib/apartment/adapters/abstract_adapter.rb | 14 ++++++++++++++ lib/apartment/adapters/postgresql_adapter.rb | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/lib/apartment/adapters/abstract_adapter.rb b/lib/apartment/adapters/abstract_adapter.rb index f8acea2a..490fdc0c 100644 --- a/lib/apartment/adapters/abstract_adapter.rb +++ b/lib/apartment/adapters/abstract_adapter.rb @@ -65,6 +65,8 @@ def drop(tenant) Apartment.connection.drop_database(config[:database]) @current = tenant + rescue *rescuable_exceptions => exception + raise_drop_tenant_error!(tenant, exception) ensure switch!(previous_tenant) rescue reset end @@ -164,9 +166,21 @@ def load_or_abort(file) end end + def rescuable_exceptions + [ActiveRecord::ActiveRecordError] + Array(rescue_from) + end + + def rescue_from + [] + end + def raise_connect_error!(tenant, exception) raise TenantNotFound, "Error while connecting to tenant #{tenant}: #{exception.message}" end + + def raise_drop_tenant_error!(tenant, exception) + raise TenantNotFound, "Error while dropping tenant #{tenant}: #{ exception.message }" + end end end end diff --git a/lib/apartment/adapters/postgresql_adapter.rb b/lib/apartment/adapters/postgresql_adapter.rb index c25f8ede..f70cd08e 100644 --- a/lib/apartment/adapters/postgresql_adapter.rb +++ b/lib/apartment/adapters/postgresql_adapter.rb @@ -80,6 +80,10 @@ def connection_specification_name(config) end end + def rescue_from + PG::Error + end + private def database_exists?(database) result = Apartment.connection.exec_query(<<-SQL).try(:first) From 825444a20f8fea0ec0e120e0075aac14124cafb3 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Tue, 12 Mar 2019 13:35:43 -0400 Subject: [PATCH 12/22] Rescue expected errors when creating tenant --- lib/apartment/adapters/abstract_adapter.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/apartment/adapters/abstract_adapter.rb b/lib/apartment/adapters/abstract_adapter.rb index 490fdc0c..b905f4fa 100644 --- a/lib/apartment/adapters/abstract_adapter.rb +++ b/lib/apartment/adapters/abstract_adapter.rb @@ -42,6 +42,8 @@ def create(tenant) seed_data if Apartment.seed_after_create yield if block_given? + rescue *rescuable_exceptions => exception + raise_create_tenant_error!(tenant, exception) ensure switch!(previous_tenant) rescue reset end @@ -178,6 +180,10 @@ def raise_connect_error!(tenant, exception) raise TenantNotFound, "Error while connecting to tenant #{tenant}: #{exception.message}" end + def raise_create_tenant_error!(tenant, exception) + raise TenantExists, "Error while creating tenant #{tenant}: #{ exception.message }" + end + def raise_drop_tenant_error!(tenant, exception) raise TenantNotFound, "Error while dropping tenant #{tenant}: #{ exception.message }" end From e3ca496776dbbd1d9488a82333f5fecdf85ba624 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Tue, 12 Mar 2019 16:25:15 -0400 Subject: [PATCH 13/22] Account for different ports and fallback to postgres db Use postgres db as default so that we can create/drop tenant databases as needed --- lib/apartment/adapters/abstract_adapter.rb | 14 ++++++++++---- lib/apartment/adapters/postgresql_adapter.rb | 5 +++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/apartment/adapters/abstract_adapter.rb b/lib/apartment/adapters/abstract_adapter.rb index b905f4fa..a87da89f 100644 --- a/lib/apartment/adapters/abstract_adapter.rb +++ b/lib/apartment/adapters/abstract_adapter.rb @@ -30,8 +30,11 @@ def create(tenant) config = config_for(tenant) difference = current_difference_from(config) - if difference[:host] - connection_switch!(config, without_keys: [:database, :schema_search_path]) + if difference[:host] || difference[:port] + default_db = "postgres" + temp_config = config.dup + temp_config[:database] = default_db + connection_switch!(temp_config) end create_tenant!(config) @@ -56,8 +59,11 @@ def drop(tenant) config = config_for(tenant) difference = current_difference_from(config) - if difference[:host] - connection_switch!(config, without_keys: [:database]) + if difference[:host] || difference[:port] + default_db = "postgres" + temp_config = config.dup + temp_config[:database] = default_db + connection_switch!(temp_config) end unless database_exists?(config[:database]) diff --git a/lib/apartment/adapters/postgresql_adapter.rb b/lib/apartment/adapters/postgresql_adapter.rb index f70cd08e..5f7369df 100644 --- a/lib/apartment/adapters/postgresql_adapter.rb +++ b/lib/apartment/adapters/postgresql_adapter.rb @@ -39,7 +39,7 @@ def switch_tenant(config) difference = config.select{ |k, v| current_config[k] != v } # PG doesn't have the ability to switch DB without reconnecting - if difference[:host] || difference[:database] + if difference[:host] || difference[:database] || difference[:port] connection_switch!(config) else simple_switch(config) if difference[:schema_search_path] @@ -75,7 +75,8 @@ def connection_specification_name(config) if Apartment.pool_per_config "_apartment_#{config.hash}".to_sym else - host_hash = Digest::MD5.hexdigest(config[:host] || config[:url] || "127.0.0.1") + value = "#{config[:host]}:#{config[:port]}" || config[:url] || "127.0.0.1" + host_hash = Digest::MD5.hexdigest(value) "_apartment_#{host_hash}_#{config[:adapter]}_#{config[:database]}".to_sym end end From 047061d5d255150ab1d2a28b99b07ab44976ef6f Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Wed, 13 Mar 2019 12:26:00 -0400 Subject: [PATCH 14/22] Actually switch the connection --- lib/apartment/adapters/abstract_adapter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/apartment/adapters/abstract_adapter.rb b/lib/apartment/adapters/abstract_adapter.rb index a87da89f..1c310a1b 100644 --- a/lib/apartment/adapters/abstract_adapter.rb +++ b/lib/apartment/adapters/abstract_adapter.rb @@ -150,6 +150,7 @@ def connection_switch!(config, without_keys: []) unless Apartment.connection_handler.retrieve_connection_pool(config[:name]) Apartment.connection_handler.establish_connection(config) + Apartment.establish_connection(config) end Thread.current[:_apartment_connection_specification_name] = config[:name] From 8838a9d1aced017bb2636a06b0926b9c85c62d61 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Wed, 13 Mar 2019 14:55:04 -0400 Subject: [PATCH 15/22] Fix seed rake task --- lib/apartment/adapters/abstract_adapter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/apartment/adapters/abstract_adapter.rb b/lib/apartment/adapters/abstract_adapter.rb index 1c310a1b..bf18c291 100644 --- a/lib/apartment/adapters/abstract_adapter.rb +++ b/lib/apartment/adapters/abstract_adapter.rb @@ -166,6 +166,7 @@ def import_database_schema def seed_data silence_warnings{ load_or_abort(Apartment.seed_data_file) } if Apartment.seed_data_file end + alias seed seed_data def load_or_abort(file) if File.exist?(file) From 12fbee2ec69e1e40711a970c66e815fa90c6be7e Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Wed, 13 Mar 2019 17:16:23 -0400 Subject: [PATCH 16/22] Clear connections after rake tasks Old connections are persisting among rake tasks called during db:reset --- lib/tasks/apartment.rake | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/tasks/apartment.rake b/lib/tasks/apartment.rake index f51fa4e9..0825f58f 100644 --- a/lib/tasks/apartment.rake +++ b/lib/tasks/apartment.rake @@ -12,6 +12,7 @@ apartment_namespace = namespace :apartment do puts e.message end end + clear_connections end desc "Drop all tenants" @@ -24,6 +25,8 @@ apartment_namespace = namespace :apartment do puts e.message end end + + clear_connections end desc "Migrate all tenants" @@ -52,6 +55,7 @@ apartment_namespace = namespace :apartment do puts e.message end end + clear_connections end desc "Rolls the migration back to the previous version (specify steps w/ STEP=n) across all tenants." @@ -131,4 +135,15 @@ apartment_namespace = namespace :apartment do WARNING end end + + def clear_connections + Apartment.connection_class.clear_all_connections! + Apartment.connection_class.connection_handler.tap do |ch| + ch.send(:owner_to_pool).each_key do |k| + ch.remove_connection(k) if k =~ /^_apartment/ + end + end + Thread.current[:_apartment_connection_specification_name] = nil + Apartment::Tenant.reload! + end end From f2bf69feecee6ce2b12dec376fd46e788e3b278a Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Thu, 14 Mar 2019 11:00:07 -0400 Subject: [PATCH 17/22] Add public method for cleaning connections - Useful for when we want to reset our state, but hold on to the config --- lib/apartment.rb | 11 +++++++++++ lib/tasks/apartment.rake | 17 +++-------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/apartment.rb b/lib/apartment.rb index 52b94faa..d15dff2a 100644 --- a/lib/apartment.rb +++ b/lib/apartment.rb @@ -86,6 +86,17 @@ def reset Thread.current[:_apartment_connection_specification_name] = nil end + + def clear_connections + connection_class.clear_all_connections! + connection_handler.tap do |ch| + ch.send(:owner_to_pool).each_key do |k| + ch.remove_connection(k) if k =~ /^_apartment/ + end + end + Thread.current[:_apartment_connection_specification_name] = nil + Apartment::Tenant.reload! + end end # Exceptions diff --git a/lib/tasks/apartment.rake b/lib/tasks/apartment.rake index 0825f58f..d76e04c9 100644 --- a/lib/tasks/apartment.rake +++ b/lib/tasks/apartment.rake @@ -12,7 +12,7 @@ apartment_namespace = namespace :apartment do puts e.message end end - clear_connections + Apartment.clear_connections end desc "Drop all tenants" @@ -26,7 +26,7 @@ apartment_namespace = namespace :apartment do end end - clear_connections + Apartment.clear_connections end desc "Migrate all tenants" @@ -55,7 +55,7 @@ apartment_namespace = namespace :apartment do puts e.message end end - clear_connections + Apartment.clear_connections end desc "Rolls the migration back to the previous version (specify steps w/ STEP=n) across all tenants." @@ -135,15 +135,4 @@ apartment_namespace = namespace :apartment do WARNING end end - - def clear_connections - Apartment.connection_class.clear_all_connections! - Apartment.connection_class.connection_handler.tap do |ch| - ch.send(:owner_to_pool).each_key do |k| - ch.remove_connection(k) if k =~ /^_apartment/ - end - end - Thread.current[:_apartment_connection_specification_name] = nil - Apartment::Tenant.reload! - end end From ca45dc0146d0acbfc3a8e1c74f83bb9926c56687 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Sun, 17 Mar 2019 08:41:13 -0400 Subject: [PATCH 18/22] Always switch to thread specific connection when possible - Fixes some issues I was seeing with tests - Add a guard to return excluded models spec name --- lib/apartment/adapters/abstract_adapter.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/apartment/adapters/abstract_adapter.rb b/lib/apartment/adapters/abstract_adapter.rb index bf18c291..4b6ce950 100644 --- a/lib/apartment/adapters/abstract_adapter.rb +++ b/lib/apartment/adapters/abstract_adapter.rb @@ -126,12 +126,10 @@ def setup_connection_specification_name Apartment.connection_class.connection_specification_name = nil Apartment.connection_class.instance_eval do def connection_specification_name - if !defined?(@connection_specification_name) || @connection_specification_name.nil? - apartment_spec_name = Thread.current[:_apartment_connection_specification_name] - return apartment_spec_name || - (self == ActiveRecord::Base ? "primary" : superclass.connection_specification_name) - end - @connection_specification_name + return :_apartment_excluded if @connection_specification_name == :_apartment_excluded + + return Thread.current[:_apartment_connection_specification_name] || + (self == ActiveRecord::Base ? "primary" : superclass.connection_specification_name) end end end From 1e9ca1f0de305db33f845fc20daf170add4ec61b Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Mon, 18 Mar 2019 14:22:11 -0400 Subject: [PATCH 19/22] Remove default_db var --- lib/apartment/adapters/abstract_adapter.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/apartment/adapters/abstract_adapter.rb b/lib/apartment/adapters/abstract_adapter.rb index 4b6ce950..aa7821f6 100644 --- a/lib/apartment/adapters/abstract_adapter.rb +++ b/lib/apartment/adapters/abstract_adapter.rb @@ -31,9 +31,8 @@ def create(tenant) difference = current_difference_from(config) if difference[:host] || difference[:port] - default_db = "postgres" temp_config = config.dup - temp_config[:database] = default_db + temp_config[:database] = "postgres" connection_switch!(temp_config) end @@ -60,9 +59,8 @@ def drop(tenant) difference = current_difference_from(config) if difference[:host] || difference[:port] - default_db = "postgres" temp_config = config.dup - temp_config[:database] = default_db + temp_config[:database] = "postgres" connection_switch!(temp_config) end From b603d6366a54d0c2fc96c6970d5a6f3be25b6dbc Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Mon, 18 Mar 2019 16:54:08 -0400 Subject: [PATCH 20/22] Add database config resolver --- lib/apartment/resolvers/config.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 lib/apartment/resolvers/config.rb diff --git a/lib/apartment/resolvers/config.rb b/lib/apartment/resolvers/config.rb new file mode 100644 index 00000000..58a1fecc --- /dev/null +++ b/lib/apartment/resolvers/config.rb @@ -0,0 +1,23 @@ +require 'apartment/resolvers/abstract' + +module Apartment + module Resolvers + class Config < Abstract + def resolve(tenant) + return init_config.dup if !tenant || tenant == Apartment.default_tenant + + database_config(tenant) + end + + private + + def database_config(tenant) + ActiveRecord::Base.configurations[config_name(tenant)].symbolize_keys + end + + def config_name(tenant) + "#{Rails.env}_#{tenant}" + end + end + end +end From 26ace7cba1a1c2c045fb78aaeaa56ca40911fada Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Tue, 19 Mar 2019 09:54:36 -0400 Subject: [PATCH 21/22] Remove extra call to establish connection --- lib/apartment/adapters/abstract_adapter.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/apartment/adapters/abstract_adapter.rb b/lib/apartment/adapters/abstract_adapter.rb index aa7821f6..35eda11b 100644 --- a/lib/apartment/adapters/abstract_adapter.rb +++ b/lib/apartment/adapters/abstract_adapter.rb @@ -146,7 +146,6 @@ def connection_switch!(config, without_keys: []) unless Apartment.connection_handler.retrieve_connection_pool(config[:name]) Apartment.connection_handler.establish_connection(config) - Apartment.establish_connection(config) end Thread.current[:_apartment_connection_specification_name] = config[:name] From 795648aaf255460872e1b568e8d32f13d40f7c93 Mon Sep 17 00:00:00 2001 From: Mike DeRosa Date: Tue, 19 Mar 2019 22:54:51 -0400 Subject: [PATCH 22/22] Call init again to ensure setup_connection_specification_name is called - If the default tenant db does not exist, setup_connection_specification_name was not getting called - Other tenants would fail to get created as a result because the switching mechanism was not triggering --- lib/tasks/apartment.rake | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tasks/apartment.rake b/lib/tasks/apartment.rake index d76e04c9..fb6b760c 100644 --- a/lib/tasks/apartment.rake +++ b/lib/tasks/apartment.rake @@ -4,6 +4,7 @@ apartment_namespace = namespace :apartment do desc "Create all tenants" task :create do + Apartment::Tenant.init tenants.each do |tenant| begin puts("Creating #{tenant} tenant")