在一个Rails 7应用程序中,使用Postgresql数据库,我有一个模型Stat
,带有一个jsonb字段data
。我有一个大的并发发生,几个异步进程将在jsonb字段data
中添加自己的行。
为了测试并发弹性,我创建了一个Rspec测试。它将键值对{"<index>" => "ok"}
添加到data
jsonb字段20次。最后,我得到一个随机长度的数据字段。如果它是弹性的,长度应该总是“20”。
threads = 20.times.map.with_index do |_, index|
Thread.new do
stat = Stat.find(stat_id)
stat.with_lock do
stat.update!(data: stat.data.merge({index => "ok"}))
end
end
end
threads.map &:join
stat = Stat.find(stat_id)
expect(stat.data.length).to eq(20)
1条答案
按热度按时间qgelzfjb1#
Rails中的默认设置是在单个事务中运行测试示例,然后在测试结束时回滚该事务以将数据库恢复到原始状态。这意味着,尽管您创建了所有这些线程,但它们都将从池中汇集到同一个DB连接中,这意味着每个线程中的锁并没有与其他线程隔离。
如果您关闭
use_transactional_fixtures
,那么您将看到您想要的行为(RSpec::Rails v6有一个用于关闭事务测试的整洁的帮助程序),尽管您还需要自己清理数据库。把这个放在你的测试中:您可能还需要增加
database.yml
中的连接池大小,以便至少有20个可用连接。