多个数据库/副本无法在Rails 6的测试环境中工作



在从distribute_reads迁移到原生Rails 6多数据库支持的过程中,我遇到了一个奇怪的行为,我仍然不确定这是错误还是配置问题。

// database.yml
default: &default
adapter: postgresql
encoding: unicode
pool: 10
reaping_frequency: 10
timeout: 5000
username: my_username
password: my_password
database: my_database
schema_search_path: 'public,utils'
development: &development
primary:
<<: *default
database: my_database
host: 'localhost'
primary_replica:
<<: *default
database: my_database
host: 'localhost'
replica: true
third_replica:
<<: *default
database: my_database
host: 'localhost'
replica: true
test: &test
primary:
<<: *default
database: 'my_database_test'
host: 'localhost'
primary_replica:
<<: *default
database: 'my_database_test'
host:'localhost'
replica: true
third_replica:
<<: *default
database: 'my_database_test'
host: 'localhost'
replica: true

我还更改了连接到此代码库的所有记录的ApplicationRecord

# application_record.rb
connects_to shards: {
default: { writing: :primary, reading: :primary_replica },
admin: { writing: :primary, reading: :third_replica }
}

现在,当我在开发时,它的行为完全符合

> ActiveRecord::Base.connected_to(role: :reading, shard: :default, prevent_writes: true) do
EventType.count
end
(72.3ms)  SELECT COUNT(*) FROM "event_types" /*line:(pry):2:in `block in <main>'*/
=> 2

这是正确的记录数。当我运行测试并使用相同的行时,包装器外的EventType.count也会计算正确的数字,但无论我在任何模型中检查什么记录,connected_to都会产生0

> EventType.count
=> 1
> ActiveRecord::Base.connected_to(role: :reading, shard: :default, prevent_writes: true) do
EventType.count
end
=> 0

开发/测试中的副本实际上是同一个数据库,所以在我的情况下不可能获得0

当使用writing角色时,它通过工作

> ActiveRecord::Base.connected_to(role: :writing, shard: :default) do
EventType.count
end
=> 1

请注意,shards:部分似乎并不重要,因为它也通过database:和没有third_replica的简化版本中断

这个Rails功能有什么我遗漏的吗?是否有与测试不兼容的内容?我找不到任何与此相关的文档。

最终,问题来自我们在整个测试设置过程中的事务

DatabaseCleaner.strategy = :transaction

它在我们的代码库中证明了这是一个更大的问题。当将查询封装到事务中并使用connected_to时,您基本上会退出所述事务,并且在我们的特定情况下会产生许多一致性问题。这完全符合逻辑,但将其添加到堆栈中可能与最初的内容不兼容。

结论是在使用事务和处理读取副本时要小心。

最新更新