49 lines
1.0 KiB
Crystal
49 lines
1.0 KiB
Crystal
require "http"
|
|
require "./fibers"
|
|
|
|
def wait_for(timeout = 5.seconds)
|
|
now = Time.monotonic
|
|
|
|
until yield
|
|
Fiber.yield
|
|
|
|
if (Time.monotonic - now) > timeout
|
|
raise "block failed to evaluate to true within #{timeout}"
|
|
end
|
|
end
|
|
end
|
|
|
|
# Helper method which runs *server*
|
|
# 1. Spawns `server.listen` in a new fiber.
|
|
# 2. Waits until `server.listening?`.
|
|
# 3. Yields to the given block.
|
|
# 4. Ensures the server is closed.
|
|
# 5. After returning from the block, it waits for the server to gracefully
|
|
# shut down before continuing execution in the current fiber.
|
|
# 6. If the listening fiber raises an exception, it is rescued and re-raised
|
|
# in the current fiber.
|
|
def run_server(server)
|
|
server_done = Channel(Exception?).new
|
|
|
|
f = spawn do
|
|
server.listen
|
|
rescue exc
|
|
server_done.send exc
|
|
else
|
|
server_done.send nil
|
|
end
|
|
|
|
begin
|
|
wait_for { server.listening? }
|
|
wait_until_blocked f
|
|
|
|
yield server_done
|
|
ensure
|
|
server.close unless server.closed?
|
|
|
|
if exc = server_done.receive
|
|
raise exc
|
|
end
|
|
end
|
|
end
|