In rspec, especially in feature specs, multiple threads can run concurrently ( for example the test itself and the test server) but they both use the same ActiveRecord database connection. Thats makes it that when a spec changes the schema by doig a SET search_path TO, then it can also affects the other threads causing unexpected behaviors. At least thats what i understood after debugging some very flaky behavior in the feature specs.
This does not happen in a normal context (development and production), it only happens during specs, especially feature specs.
Is there an existing solution for this kind of bugs? meanwhile, if other people encounter the same problem i have a working fix by adding a monkey-patch in a spec/support file:
# patch to fix concurrency problem in test mode. In test mode, you can have multiple threads
# that uses the same ActiveRecord connection. Each thread has its own instance of apartment
# and can do a Tenant.switch!. This cause other threads to start using the wrong schema.
# with this patch, before every single sql query, we validate that we are doing it in the
# correct schema. If we are not in the correct schema, we switch. This is not optimal and causes
# a lot of overhead, but luckily its a test-only problem.
module ApartmentExtension
def exec_query(sql, name = "SQL", binds = [], prepare: false, async: false)
raise unless Rails.env.test? # this patch is for tests only, do not use in dev/prod!
@lock.synchronize do
current_schema_name = get_current_schema
if current_schema_name && current_schema_name != Apartment::Tenant.current
Apartment::Tenant.switch!(Apartment::Tenant.current)
end
super(sql, name, binds, prepare: prepare, async: async)
end
end
def get_current_schema
current_schema
rescue
nil
end
end
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
prepend ApartmentExtension
end
System configuration
Database: postgres 14
Apartment version: 2.11
Apartment config (in config/initializers/apartment.rb or so):
Steps to reproduce
In rspec, especially in feature specs, multiple threads can run concurrently ( for example the test itself and the test server) but they both use the same ActiveRecord database connection. Thats makes it that when a spec changes the schema by doig a
SET search_path TO
, then it can also affects the other threads causing unexpected behaviors. At least thats what i understood after debugging some very flaky behavior in the feature specs.This does not happen in a normal context (development and production), it only happens during specs, especially feature specs.
Is there an existing solution for this kind of bugs? meanwhile, if other people encounter the same problem i have a working fix by adding a monkey-patch in a
spec/support
file:System configuration
Database: postgres 14
Apartment version: 2.11
Apartment config (in
config/initializers/apartment.rb
or so):use_schemas
:true
Rails (or ActiveRecord) version: 7.0.8
Ruby version: 3.2.1