2011-01-13 41 views
1

有没有什么方法可以使用RSpec来测试并行事务? 说我有一个银行账户余额,需要在一个交易中被锁定,然后它被减少或增加。 但是,目前,虽然我关闭了RSpec transactional_fixtures选项,但我无法在两个分离的线程中启动2个并行事务。出于某种原因,两者都被挂起。 定帐户的模型 然后这个规范将挂起:使用RSpec测试并行事务

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 

有没有什么办法让它不挂,同时仍然能够证明交易的能力吗?

回答

0

我想不出一个很好的理由,为什么你想要在同一个资源上进行并行事务。你在你的例子中究竟想达到什么目的?

在您的代码中,您使用的是同一个实例,因此预计会陷入死锁。你可能想要重新考虑你想在这里做什么。

+0

你是说AR缓存我的`Account.find()`结果吗? – 2011-04-03 02:17:28

1

您需要在线程中使用不同的数据库连接。首先,断开主线程,然后重新连接在每个线程,终于重新连接主,像这样:

ActiveRecord::Base.connection.disconnect! 
(0..1).each do |index| 
    threads << Thread.new do 
    ActiveRecord::Base.establish_connection 
    # ... 
    end 
end 
ActiveRecord::Base.establish_connection 

有在测试这样的其他问题:你有没有在那里并发发生点的保证。红宝石GIL也无济于事。你应该使用fork来代替线程,或者使用fork_break gem:https://github.com/remen/fork_break