Distribution_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 を取得することはできないはずです。
書き込みロールを使用する場合は機能しますが、
> ActiveRecord::Base.connected_to(role: :writing, shard: :default) do
EventType.count
end
=> 1
shards: の部分は、database: を介した簡易バージョンでも壊れ、 third_replica がないため、重要ではないようです。
この Rails 機能について何か足りないものはありますか?これと互換性のないテストに関連するものはありますか?これに関連するドキュメントは見つかりませんでした。
結局、問題はテスト設定全体を通して発生したトランザクションに起因していました。
DatabaseCleaner.strategy = :transaction
そして、それが私たちのコードベース全体ではるかに大きな問題であるという証拠を示しました。クエリをトランザクションにラップし、connected_to を使用すると、基本的にそのトランザクションから抜け出すことになり、この特定のケースでは多くの一貫性の問題が発生します。これは純粋に論理的ですが、これをスタックに追加すると、最初に存在したものと互換性がなくなる可能性があります。
結論としては、トランザクションを使用するときとリードレプリカを扱うときは注意する必要があります。