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

问题描述 投票:0回答:2

在努力从 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 功能的某些内容?是否存在与此不兼容的测试相关的内容?我找不到与此相关的任何文档。

ruby-on-rails ruby database-replication
2个回答
0
投票

最后,问题来自于我们在整个测试设置中的事务

DatabaseCleaner.strategy = :transaction

这证明这是我们代码库中一个更大的问题。当将查询包装到事务中并使用

connected_to
时,您基本上会脱离所述事务,并且在我们的特定情况下会产生很多一致性问题。这纯粹是逻辑上的,但将其添加到堆栈中可能与最初的内容不兼容。

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


0
投票

Laurent 你是否能够解决这个问题,因为在 rspec 中,它只发生在事务块中,只有你在 rspec 中为此做了任何解决方法,因为在开发中它工作正常。 预先感谢,我无法发表评论,因为我没有声誉

© www.soinside.com 2019 - 2024. All rights reserved.