Wait for all server requests to finish on session reset

This commit is contained in:
John Hawthorn 2015-07-06 16:19:47 -07:00 committed by Thomas Walpole
parent 4b3093f4bd
commit 998350091b
3 changed files with 55 additions and 0 deletions

View File

@ -4,22 +4,47 @@ require 'rack'
module Capybara
class Server
class Counter
attr_reader :value
def initialize
@value = 0
@mutex = Mutex.new
end
def increment
@mutex.synchronize { @value += 1 }
end
def decrement
@mutex.synchronize { @value -= 1 }
end
end
class Middleware
attr_accessor :error
def initialize(app)
@app = app
@counter = Counter.new
end
def pending_requests?
@counter.value > 0
end
def call(env)
if env["PATH_INFO"] == "/__identify__"
[200, {}, [@app.object_id.to_s]]
else
@counter.increment
begin
@app.call(env)
rescue *Capybara.server_errors => e
@error = e unless @error
raise e
ensure
@counter.decrement
end
end
end
@ -62,6 +87,12 @@ module Capybara
return false
end
def wait_for_pending_requests
Timeout.timeout(60) { sleep(0.01) while @middleware.pending_requests? }
rescue Timeout::Error
raise "Requests did not finish in 60 seconds"
end
def boot
unless responsive?
Capybara::Server.ports[@app.object_id] = @port

View File

@ -109,6 +109,7 @@ module Capybara
assert_no_selector :xpath, "/html/body/*" if driver.browser_initialized?
@touched = false
end
@server.wait_for_pending_requests if @server
raise_server_error!
end
alias_method :cleanup!, :reset!

View File

@ -113,4 +113,27 @@ RSpec.describe Capybara::Server do
expect(Net::HTTP).to receive(:start).and_raise(SystemCallError.allocate)
expect(server.responsive?).to eq false
end
it "can detect and wait for pending requests" do
done = false
app = proc do |env|
sleep 0.2
done = true
[200, {}, ["Hello Server!"]]
end
server = Capybara::Server.new(app).boot
# Start request, but don't wait for it to finish
socket = TCPSocket.new(server.host, server.port)
socket.write "GET / HTTP/1.0\r\n\r\n"
socket.close
sleep 0.1
expect(done).to be false
server.wait_for_pending_requests
# Ensure server was allowed to finish
expect(done).to be true
end
end