Skip to content

Commit 64f57c2

Browse files
committed
Use custom class for pending migrations connection
In bensheldon/good_job#1103 it was reported that a connection not established is being seen when there are multiple configs for an environment (a multi-db app). While I think that something is happening where Good Job is accessing the connection while we're checking for pending migrations, this could happen in other gems if we're clobbering the connection on `ActiveRecord::Base` that is needed. Here we are making a special class to establish connections to the database. Because the class does not inherit from `Base` and establishes it's own connection, it won't clobber any existing connections on `Base`, leaving them in-tact while the app boots. The reason this wasn't seen in 7.0 is because pending migrations didn't check all the available configs. Once that was fixed this error appeared. I didn't add a test for this because it's really hard to reproduce without good job and actually booting a server and running a request. Fixes: rails#49689
1 parent cae5baf commit 64f57c2

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

activerecord/lib/active_record/migration.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
require "active_support/core_ext/enumerable"
88
require "active_support/core_ext/module/attribute_accessors"
99
require "active_support/actionable_error"
10+
require "active_record/migration/pending_migration_connection"
1011

1112
module ActiveRecord
1213
class MigrationError < ActiveRecordError # :nodoc:
@@ -768,9 +769,11 @@ def db_configs_in_current_env
768769
def pending_migrations
769770
pending_migrations = []
770771

771-
ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: env) do |connection|
772-
if pending = connection.migration_context.open.pending_migrations
773-
pending_migrations << pending
772+
ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
773+
ActiveRecord::PendingMigrationConnection.establish_temporary_connection(db_config) do |conn|
774+
if pending = conn.migration_context.open.pending_migrations
775+
pending_migrations << pending
776+
end
774777
end
775778
end
776779

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
module ActiveRecord
4+
class PendingMigrationConnection # :nodoc:
5+
def self.establish_temporary_connection(db_config, &block)
6+
pool = ActiveRecord::Base.connection_handler.establish_connection(db_config, owner_name: self)
7+
8+
yield pool.connection
9+
ensure
10+
ActiveRecord::Base.connection_handler.remove_connection_pool(self.name)
11+
end
12+
13+
def self.primary_class?
14+
false
15+
end
16+
17+
def self.current_preventing_writes
18+
false
19+
end
20+
end
21+
end

0 commit comments

Comments
 (0)