我的 API 允许用户购买某些独特的物品,其中每件物品只能卖给一个用户。因此,当多个用户尝试购买同一个商品时,一个用户应该得到响应:ok,另一个用户应该得到响应too_late。
现在,我的代码中似乎存在错误。比赛条件。如果两个用户同时尝试购买相同的商品,他们都会得到ok的答案。这个问题在生产中显然是可以重现的。现在我编写了一个简单的测试,试图通过 rspec 重现它:
context "when I try to provoke a race condition" do
# ...
before do
@concurrent_requests = 2.times.map do
Thread.new do
Thread.current[:answer] = post "/api/v1/item/buy.json", :id => item.id
end
end
@answers = @concurrent_requests.map do |th|
th.join
th[:answer].body
end
end
it "should only sell the item to one user" do
@answers.sort.should == ["ok", "too_late"].sort
end
end
似乎没有同时执行查询。为了测试这一点,我将以下代码放入我的控制器操作中:
puts "Is it concurrent?"
sleep 0.2
puts "Oh Noez."
如果请求是并发的,则预期的输出将是:
Is it concurrent?
Is it concurrent?
Oh Noez.
Oh Noez.
但是,我得到以下输出:
Is it concurrent?
Oh Noez.
Is it concurrent?
Oh Noez.
这告诉我,capybara 请求不是同时运行的,而是一次运行一个。如何使我的 capabara 请求并发?