Remove global read_timeout default, add watcher-level idle timeout#1945
Merged
Conversation
Signed-off-by: doxxx93 <doxxx93@gmail.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1945 +/- ##
=======================================
- Coverage 76.5% 76.5% -0.0%
=======================================
Files 89 89
Lines 8566 8587 +21
=======================================
+ Hits 6547 6563 +16
- Misses 2019 2024 +5
🚀 New features to boost your workflow:
|
Signed-off-by: doxxx93 <doxxx93@gmail.com>
Member
Author
|
|
clux
reviewed
Mar 27, 2026
clux
reviewed
Mar 27, 2026
clux
reviewed
Mar 27, 2026
clux
reviewed
Mar 27, 2026
clux
reviewed
Mar 27, 2026
clux
left a comment
Member
There was a problem hiding this comment.
Thanks for this. Sorry took me a while to get to it.
Left a few comments on some documentation choices, but otherwise the wrapping function here is a very nice solution.
Signed-off-by: doxxx93 <doxxx93@gmail.com>
clux
approved these changes
Mar 27, 2026
atilladeniz
added a commit
to atilladeniz/Kubeli
that referenced
this pull request
Apr 26, 2026
Closes #292. The shared kube-rs client set `read_timeout = 30s`, which kube-client forwards to hyper-timeout's per-read timer on the underlying I/O. Any long-lived idle stream (`pods.log_stream`, `pods.exec`) was therefore torn down after ~30s of silence and surfaced in the UI as "ServiceError: error reading a body from connection". Leave `read_timeout` and `write_timeout` unset on the shared client so streams stay open until the user, the pod, or the API server closes them. This matches the new kube-rs upstream default (PR kube-rs/kube#1945) and the behavior of kubectl / the Go client. `connect_timeout = 10s` is preserved so bad clusters still fail fast at connection time. Per-request deadlines for non-streaming calls already live at the call site via `tokio::time::timeout` (see `test_connection`). Apply the same policy in both client paths: - `init_with_context`, used by the Tauri app via `commands/clusters.rs` - `init`, used by the MCP server via `mcp/server.rs::connect_to_cluster` A previously-stale `#[allow(dead_code)]` on `init` was removed; the function is in fact wired up through MCP. Adds a regression test (`shared_client_has_no_read_timeout`) that pins the timeout policy so a future change cannot silently reintroduce the bug. Follow-up tracked in #296: replace the raw `ServiceError` banner with an inline "Stream ended" notice plus a Reconnect button, since the same error surface still fires for legitimate stream ends (pod terminated, kubelet idle timeout, LB cuts, etc.).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1798
Motivation
The default
config.read_timeout(295s) is applied at thehyper-timeoutconnector level, which enforces an idle timeout on all TCP I/O indiscriminately. This breaks long-lived connections like exec, attach, and port-forward — if there's no stdin/stdout activity for 295s, the connection is killed with a broken pipe.The Go client has no global read timeout. Watch streams rely on the server-side
timeoutSecondsparameter instead.Verified on a kind cluster (v1.35.0): exec connections die after idle with
read_timeoutset, but survive indefinitely withNone.Solution
Default
read_timeouttoNonein allConfigconstructors, matching the Go client behavior.Add a watcher-level idle timeout (
next_with_idle_timeout) that wrapsstream.next()withtokio::time::timeout. The timeout is set to the server-sidetimeoutSeconds+ 5s margin, so watches still recover from dead connections where the server's close never arrives.This way each timeout is owned by the layer that actually needs it: