DEV: Use MiniSql ActiveRecordPostgres adapter (#15767)

This adapter ensures that MiniSql locks the ActiveRecord mutex before using the raw PG connection. This ensures that multiple threads will not attempt to use the same connection simultaneously.

This commit also removes the schema_cache_concurrency freedom-patch, which is no longer required now that cross-thread connection use is controlled by the mutex.

For the original root cause of this issue, see https://github.com/rails/rails/pull/38577
This commit is contained in:
David Taylor 2022-02-03 10:00:28 +00:00 committed by GitHub
parent d0d8e25092
commit 3f6c2f82d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 4 additions and 31 deletions

View File

@ -236,7 +236,7 @@ GEM
libv8-node (~> 16.10.0.0)
mini_scheduler (0.13.0)
sidekiq (>= 4.2.3)
mini_sql (1.1.3)
mini_sql (1.3.0)
mini_suffix (0.3.3)
ffi (~> 1.9)
minitest (5.15.0)

View File

@ -1,27 +0,0 @@
# frozen_string_literal: true
#
# Rails has a circular dependency in SchemaCache.
# In certain situation SchemaCache can carry a @connection
# from a different thread. This causes potential concurrency bugs
# in Sidekiq.
#
# This patches it so it is less flexible (theoretically) but always bound to the current connection
# This patch needs to be reviewed in future versions of Rails.
# We should consider upstreaming this optionally.
module ActiveRecord
module ConnectionAdapters
class SchemaCache
def connection=(connection)
# AbstractPool get_schema_cache does schema_cache.connection = connection
Thread.current["schema_cached_connection"] = connection
end
def connection
Thread.current["schema_cached_connection"]
end
end
end
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
class MiniSqlMultisiteConnection < MiniSql::Postgres::Connection
class MiniSqlMultisiteConnection < MiniSql::ActiveRecordPostgres::Connection
class CustomBuilder < MiniSql::Builder
@ -78,8 +78,8 @@ class MiniSqlMultisiteConnection < MiniSql::Postgres::Connection
# we need a tiny adapter here so we always run against the
# correct multisite connection
def raw_connection
ActiveRecord::Base.connection.raw_connection
def active_record_connection
ActiveRecord::Base.connection
end
# make for a multisite friendly prepared statement cache