使用 RSpec 测试并行事务 [英] Testing parallel transactions using RSpec
问题描述
有没有办法使用 RSpec 测试并行事务?说我有一个银行账户余额需要在减少或增加之前锁定在交易中.但是,目前,虽然我关闭了 RSpec transactional_fixtures
选项,但我无法在两个单独的线程中启动 2 个并行事务.出于某种原因,两者都挂了.给定帐户是一个模型然后这个规范将挂起:
Is there any way to test parallel transaction using RSpec?
Saying I have a bank account balance that need to be locked inside a transaction before it is decreased or increased.
However, currently, although I have turned off RSpec transactional_fixtures
option, I cannot launch 2 parallel transaction in two separated threads. For some reason, both are hung.
Given Account is a model
Then this spec will hang:
it "should ensure operations are performed correctly" do
@account = Account.create(:balance => 0)
threads = []
(0..1).each do |index|
threads << Thread.new do
Account.transaction do
account = Account.find(@account.id, :lock => true)
account.balance += 100
sleep 0.5
account.save!
end
end
end
threads.each{|t|t.join}
@account.reload.balance.should == 200
end
有什么办法可以不挂掉,同时还能展示交易能力?
Is there any way to make it not hang while still be able to demonstrate the ability of transaction?
推荐答案
您需要在线程中使用不同的数据库连接.首先断开主线程,然后在每个线程中重新连接,最后在主线程中重新连接,如下所示:
You need to use different connections to the database in your threads. First, disconnect the main thread, then reconnect in each thread, and finally reconnect in the main, like so:
ActiveRecord::Base.connection.disconnect!
(0..1).each do |index|
threads << Thread.new do
ActiveRecord::Base.establish_connection
# ...
end
end
ActiveRecord::Base.establish_connection
以这种方式进行测试还存在其他问题:您无法保证并发发生的点.ruby GIL 也无济于事.你应该使用 fork 而不是线程,或者使用 fork_break gem:https://github.com/remen/fork_break一个>
There are other problems in testing that way: You have no guarantee of the point where concurrency happens. The ruby GIL will also not help. You should use forks instead of threads, or use the fork_break gem: https://github.com/remen/fork_break
这篇关于使用 RSpec 测试并行事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!