Timeouts

Burl has three timeouts, each guarding a different part of a request: how long connecting may take, how long any single read or write may stall, and how long the whole operation may run. They are set on the client, and the whole-operation timeout can be overridden per request.

The Three Timeouts

Setting Guards

config::connect_timeout

Establishing a connection: name resolution, the TCP connection, proxy negotiation, and the TLS handshake. Defaults to 60 seconds.

config::io_timeout

Each individual read and write. Bounds how long the peer may go silent, independent of message size. Off by default.

config::timeout

The whole operation, from connecting through receipt of the response headers. Whatever time is left then bounds reading the body in place. Off by default.

They address different failure modes and are meant to be combined. The connect timeout catches an unreachable host quickly. The I/O timeout catches a peer that accepts a connection but then stalls partway through a transfer. Each read or write resets it, so a large but steady transfer is never penalized for its size. The overall timeout puts a ceiling on total latency regardless of how the time is spent.

Per-Request Override

The builder’s timeout overrides config::timeout for one request:

auto r = co_await client.get("https://example.com/report")
    .timeout(std::chrono::seconds(3))
    .send();

What a Timeout Looks Like

An expired timeout fails the operation with capy::error::timeout:

auto [ec, r] = co_await client.get(url).send();
if(ec == capy::error::timeout)
    std::cerr << "timed out\n";

Next Steps