Skip to main content

Module net

Module net 

Source
Expand description

The transport boundary: what is retried and what never is.

Moved here from private-gunnar-ops/xtask/src/remote/net.rs (lane T14, 2026-09-21) so the ONE wire implementation of crate::UpCloudApi carries the same policy every client in that crate already had — and so that crate’s other HTTP clients (Cloudflare, the health probe) re-use this copy instead of keeping a second one.

MEASURED 2026-09-20, the live bring-up: GET /1.3/price on the account answered “error sending request for url” ONCE, and a credential probe turned that one dropped connection into “provider unavailable”. The token was fine. The link hiccuped.

§The boundary, and it is not negotiable in the permissive direction

  • TRANSPORT — the question never reached the far end, or its answer never came back whole: a refused connection, a reset, a timeout, a name that did not resolve, a TLS handshake that fell over, an HTTP/1.1 framing error mid-flight. Nobody composed that; it is the wire. RETRYABLE, with a bounded budget and a backoff, and every retry is printed so a flaky link can never be mistaken for a healthy one.
  • PROTOCOL — the far end understood the question and composed an answer: a status code, a refusal body, a URI this crate built wrong. That is DATA. It is never retried and never softened. A 401 is a revoked credential, a 403 is a scope, a 412 is UpCloud saying out_of_stock, a 404 is an absence — and retrying any of them turns a clear refusal into a hang.

Every client in this crate is built with http_status_as_error(false), so a status code never even arrives here as an Err: it comes back as an ordinary response and is judged by the code that asked. That is not an accident, it is the boundary made structural — the only thing this module can see is the wire.

Structs§

Budget
How long the wire is given to stop hiccuping.

Enums§

Side
Which side of the boundary an error fell on.

Functions§

call
Run op, retrying ONLY what side calls Transport, saying every retry out loud. what names the call in the line that is printed and in the error.
call_with
call, with the clock and the voice injected so the budget can be tested without a test that sleeps.
never_sent
Did this failure happen BEFORE a single byte of the request went out?
side
Classify a ureq error. The match is on the VARIANT, not on the text of the message, because a message is a sentence someone can reword and a variant is a decision the library made.