Skip to content

fix: no limit on response duration, only stall guards - #11

Merged
Marketen merged 1 commit into
mainfrom
fix/no-response-duration-limit
Oct 15, 2026
Merged

Marketen merged 1 commit into
mainfrom
fix/no-response-duration-limit

Conversation

@Marketen

Copy link
Copy Markdown
Contributor

Summary

The Gateway cut every response at five minutes: an absolute server write deadline, plus total-duration deadlines on provider requests. Healthy long answers and streams ended mid-response.

Client side

  • The server has no absolute write deadline any more.
  • Each read from and write to the client is bounded on its own (CLIENT_IO_TIMEOUT_SECONDS, default 60 s). Transfers are split into chunks of at most 32 KiB and the deadline refreshes on progress, so a transfer that keeps moving is never cut. This also covers encrypted (EHBP) streams.
  • Request headers keep their 30 s limit.

Provider side

  • Provider requests have no total deadline.
  • A request ends only when the provider sends nothing, neither headers nor bytes, for PROVIDER_SILENCE_TIMEOUT_SECONDS (default 900 s). Keepalive bytes count as activity.
  • Tinfoil's verified transport is not replaced; only the wait for headers is bounded around it.

Both settings must be positive whole seconds; the Gateway refuses to start otherwise.

Compatibility

  • Deploy after feat: keep the credit hold alive while inference runs #10 and dappnode/dappnode-nexus#143. Responses can now last longer than Metering's reservation TTL, and without hold renewal those requests would go unbilled.
  • Edge proxies still apply. Proxies in front of the Gateway keep their own timeouts for silent connections.

Tests

  • Unit:
    • a stream with steady writes outlives the old deadline;
    • an encrypted stream refreshes its network write deadline;
    • upload reads are bounded per read and cleared after the body;
    • provider silence ends a request and keepalive bytes keep it open;
    • the header wait is bounded without limiting the body;
    • invalid settings are rejected.
  • Together with feat: keep the credit hold alive while inference runs #10: the merged tree passes the full suite. End to end with a 2-second silence guard and lease, a 6-second response with keepalives completed and was billed.

🤖 Generated with Claude Code

The Gateway cut every response at five minutes: an absolute server write
deadline, plus total-duration deadlines on provider requests. Healthy long
answers and streams ended mid-response.

- The server has no absolute write deadline. Each client read and write is
  bounded on its own (CLIENT_IO_TIMEOUT_SECONDS, default 60), in chunks of at
  most 32 KiB with the deadline refreshed on progress, so a long transfer
  that keeps moving is never cut. Request headers keep a 30 s limit.
- Provider requests have no total deadline. They end only when the provider
  sends nothing, neither headers nor bytes, for
  PROVIDER_SILENCE_TIMEOUT_SECONDS (default 900). Keepalive bytes count as
  activity. Tinfoil's verified transport keeps its own client; only the wait
  for headers is bounded around it.
- Both settings must be positive whole seconds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Marketen
Marketen merged commit 7ed69cb into main Oct 15, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant