transport: bump QUIC idle timeout + keep-alive for long cargo runs #22

Merged
osobh merged 1 commits from fix-quic-idle-during-cargo-build into main 2026-07-12 13:09:08 +00:00
+25 -2
View File
@@ -44,7 +44,18 @@ pub const CLAWSTOR_RPC_ALPN: &[u8] = b"clawstor-rpc/1";
/// Idle timeout on connection — if no data for this long the connection /// Idle timeout on connection — if no data for this long the connection
/// dies. Short enough to notice partitions, long enough to survive a /// dies. Short enough to notice partitions, long enough to survive a
/// paused laptop. /// paused laptop.
const IDLE_TIMEOUT: Duration = Duration::from_secs(30); /// Field finding 2026-07-12: raised from 30s to 10min because a long
/// `cargo build` between the initial connect and the follow-up upload
/// would silently kill the QUIC connection on `open_bi`. Cargo builds
/// on real workspaces routinely run for minutes; the idle timeout is
/// there to detect crashed peers, not to enforce interaction cadence.
const IDLE_TIMEOUT: Duration = Duration::from_secs(600);
/// Field finding 2026-07-12: keep the connection warm with a ping
/// every KEEP_ALIVE_INTERVAL — cheap belt-and-braces on top of the
/// larger idle window so cargo runs longer than the idle timeout
/// still stay dialed.
const KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(15);
/// Cap on any single RPC message payload. Ping/pong is tiny; other RPCs /// Cap on any single RPC message payload. Ping/pong is tiny; other RPCs
/// stream larger payloads via streams-of-many-messages. Prevents an /// stream larger payloads via streams-of-many-messages. Prevents an
@@ -441,7 +452,19 @@ impl QuicClient {
let client_crypto = build_client_crypto(&identity)?; let client_crypto = build_client_crypto(&identity)?;
let quic_crypto = quinn::crypto::rustls::QuicClientConfig::try_from(client_crypto) let quic_crypto = quinn::crypto::rustls::QuicClientConfig::try_from(client_crypto)
.context("wrapping rustls ClientConfig for quinn")?; .context("wrapping rustls ClientConfig for quinn")?;
let client_config = ClientConfig::new(Arc::new(quic_crypto)); let mut client_config = ClientConfig::new(Arc::new(quic_crypto));
// Field finding 2026-07-12: apply the raised idle timeout + a
// keep-alive so a long cargo build between the initial connect
// and a follow-up upload doesn't kill the connection.
let mut transport = quinn::TransportConfig::default();
transport
.max_idle_timeout(Some(
VarInt::from_u64(IDLE_TIMEOUT.as_millis() as u64)
.expect("idle timeout fits u64")
.into(),
))
.keep_alive_interval(Some(KEEP_ALIVE_INTERVAL));
client_config.transport_config(Arc::new(transport));
let endpoint = Endpoint::client(bind_addr).context("binding quinn client endpoint")?; let endpoint = Endpoint::client(bind_addr).context("binding quinn client endpoint")?;
Ok(Self { Ok(Self {
endpoint, endpoint,