gpt4 book ai didi

ruby-on-rails - 多线程并发 Capybara 请求?

转载 作者:行者123 更新时间:2023-12-04 01:40:11 29 4
gpt4 key购买 nike

我的 API 允许用户购买某些独特的物品,其中每件物品只能出售给一个用户。因此,当多个用户尝试购买同一件商品时,一个用户应该得到响应:ok,而另一个用户应该得到响应 too_late。

现在,我的代码中似乎存在错误。竞争条件。如果两个用户同时尝试购买相同的商品,他们都会得到正确的答案。该问题在生产中显然可以重现。现在我编写了一个简单的测试,试图通过 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

似乎不会同时执行查询。为了测试这一点,我将以下代码放入我的 Controller 操作中:
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 请求并发?

最佳答案

多线程和 capybara 不起作用,因为 Capabara 使用单独的服务器线程来按顺序处理连接。但是如果你 fork ,它就起作用了。

我使用退出代码作为进程间通信机制。如果你做更复杂的事情,你可能想要使用套接字。

这是我快速而肮脏的黑客:

before do
@concurrent_requests = 2.times.map do
fork do
# ActiveRecord explodes when you do not re-establish the sockets
ActiveRecord::Base.connection.reconnect!

answer = post "/api/v1/item/buy.json", :id => item.id

# Calling exit! instead of exit so we do not invoke any rspec's `at_exit`
# handlers, which cleans up, measures code coverage and make things explode.
case JSON.parse(answer.body)["status"]
when "accepted"
exit! 128
when "too_late"
exit! 129
end
end
end

# Wait for the two requests to finish and get the exit codes.
@exitcodes = @concurrent_requests.map do |pid|
Process.waitpid(pid)
$?.exitstatus
end

# Also reconnect in the main process, just in case things go wrong...
ActiveRecord::Base.connection.reconnect!

# And reload the item that has been modified by the seperate processs,
# for use in later `it` blocks.
item.reload
end

it "should only accept one of two concurrent requests" do
@exitcodes.sort.should == [128, 129]
end

我使用相当奇特的退出代码,如 128 和 129,因为如果没有到达 case 块,进程退出代码为 0,如果发生异常则退出代码为 1。两者都不应该发生。所以通过使用更高的代码,我会注意到什么时候出错了。

关于ruby-on-rails - 多线程并发 Capybara 请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11206861/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com