Skip to content

Dispatcher HTTP calls have no connect bound: a black-holed server hangs the CLI for 30s #182

Description

@Sootopolis

Surfaced while fixing the use-club verify probe (#173). Every Dispatcher call goes out on Client.default with no timeout of its own, so against a host that accepts nothing (a black-holed IP, a wedged box, a wrong api_url) the CLI sits on zio-http's 30s connect default before reporting anything.

Measured with a stub that failed to accept:

$ ccas club remove devon-chess
error: cannot reach http://127.0.0.1:8099 — start a server with 'ccas server up'.
       (connection timed out after 30000 ms: /127.0.0.1:8099)

The message is good; the 30s wait before it is not. A refused connection is instant (the common "server is down" case), so this only bites a reachable-but-not-accepting host — but that is exactly the misconfigured-api_url case a new user hits.

Note the non-obvious part

use-club's probe now bounds itself, and getting that right needed more than adding .timeout:

.provide(Client.default)
.disconnect          // plain `timeout` AWAITS the interrupted fiber
.timeout(VerifyTimeout)   // and must sit OUTSIDE `provide` to cover layer acquire/release

Without disconnect the "2s" bound measured 31s, because NettyConnectionPool.createChannel is uninterruptible with a 30s connect default and timeout waits for that region to unwind. Any fix here needs the same treatment — a naive .timeout on the Dispatcher calls will not do what it looks like it does.

Suggested shape

A connect/response bound configured once where the client is built, rather than sprinkled per call site — Dispatcher.dispatch already has the single .provide(Client.default) chokepoint. Consider zio.http.ZClient.Config connection timeout instead of a ZIO-level timeout, which would bound the connect natively and avoid the uninterruptible-unwind problem entirely. Long-running streaming follows (ccas logs, job following) must be exempt — they are meant to stay open for the life of a job, so any bound belongs on connect, not on the overall request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:cliCLI binary (subcommands, completions, config, packaging)bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions