From f0da5a5625857ffd042366ba5a47cd326d7f5ff1 Mon Sep 17 00:00:00 2001 From: "ryan.dougherty" Date: Tue, 17 Jun 2025 14:20:05 -0700 Subject: [PATCH 1/4] Increased timeouts to account for large QCTRL circuit compilation --- qcs-api-client-common/src/backoff.rs | 9 ++++-- qcs-api-client-grpc/src/tonic/channel.rs | 35 +++++++++++++++++++----- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/qcs-api-client-common/src/backoff.rs b/qcs-api-client-common/src/backoff.rs index 0cc5c7f..94157da 100644 --- a/qcs-api-client-common/src/backoff.rs +++ b/qcs-api-client-common/src/backoff.rs @@ -12,14 +12,17 @@ pub use ::backoff::*; /// Create a default [`ExponentialBackoff`] for use with QCS. /// -/// This backoff will retry for up to 5 minutes, with a maximum interval of 30 seconds and some -/// randomized jitter. +/// This backoff will retry for up to 5 minutes. The initial interval is 30 seconds, +/// and the backoff will double the interval each time it is used, up to the maximum +/// interval of 2 minutes. #[allow(clippy::module_name_repetitions)] #[must_use] pub fn default_backoff() -> ExponentialBackoff { ExponentialBackoffBuilder::new() .with_max_elapsed_time(Some(Duration::from_secs(300))) - .with_max_interval(Duration::from_secs(30)) + .with_initial_interval(Duration::from_secs(30)) + .with_max_interval(Duration::from_secs(120)) + .with_multiplier(2.0) .build() } diff --git a/qcs-api-client-grpc/src/tonic/channel.rs b/qcs-api-client-grpc/src/tonic/channel.rs index 1c539a1..fea027f 100644 --- a/qcs-api-client-grpc/src/tonic/channel.rs +++ b/qcs-api-client-grpc/src/tonic/channel.rs @@ -146,6 +146,8 @@ pub struct ChannelBuilder { endpoint: Endpoint, #[cfg(feature = "tracing")] trace_layer: CustomTraceLayer, + http_proxy: Option, + https_proxy: Option, options: O, } @@ -164,6 +166,8 @@ impl From for ChannelBuilder<()> { #[cfg(not(feature = "tracing"))] return Self { endpoint, + http_proxy: None, + https_proxy: None, options: (), }; } @@ -400,9 +404,13 @@ fn get_uri_socks_auth(uri: &Uri) -> Result, url::ParseError> { /// # Errors /// /// See [`ChannelError`]. -pub fn get_channel(uri: Uri) -> Result { +pub fn get_channel( + uri: Uri, + http_proxy: Option, + https_proxy: Option, +) -> Result { let endpoint = get_endpoint(uri); - get_channel_with_endpoint(&endpoint) + get_channel_with_endpoint(&endpoint, http_proxy, https_proxy) } /// Get a [`Channel`] to the given [`Uri`], with an optional timeout. If set to [`None`], no timeout is @@ -423,10 +431,12 @@ pub fn get_channel(uri: Uri) -> Result { /// See [`ChannelError`]. pub fn get_channel_with_timeout( uri: Uri, + https_proxy: Option, + http_proxy: Option, timeout: Option, ) -> Result { let endpoint = get_endpoint_with_timeout(uri, timeout); - get_channel_with_endpoint(&endpoint) + get_channel_with_endpoint(&endpoint, https_proxy, http_proxy) } /// Get a [`Channel`] to the given [`Endpoint`]. Useful if [`get_channel`] or @@ -448,9 +458,18 @@ pub fn get_channel_with_timeout( /// /// Returns a [`ChannelError`] if the channel cannot be constructed. #[allow(clippy::similar_names)] // http(s)_proxy are similar but precise in this case. -pub fn get_channel_with_endpoint(endpoint: &Endpoint) -> Result { - let https_proxy = get_env_uri("HTTPS_PROXY")?; - let http_proxy = get_env_uri("HTTP_PROXY")?; +pub fn get_channel_with_endpoint( + endpoint: &Endpoint, + mut https_proxy: Option, + mut http_proxy: Option, +) -> Result { + if https_proxy.is_none() { + https_proxy = get_env_uri("HTTPS_PROXY")?; + } + + if http_proxy.is_none() { + http_proxy = get_env_uri("HTTP_PROXY")?; + } let mut connector = HttpConnector::new(); connector.enforce_http(false); @@ -523,8 +542,10 @@ pub fn get_channel_with_endpoint(endpoint: &Endpoint) -> Result, + http_proxy: Option, ) -> Result, Error> { - wrap_channel(get_channel(uri)?) + wrap_channel(get_channel(uri, https_proxy, http_proxy)?) } /// Set up the given `channel` with QCS authentication. From 85f64a78dd335fb5521a2bf46f5a9adab0fffc71 Mon Sep 17 00:00:00 2001 From: "ryan.dougherty" Date: Wed, 18 Jun 2025 10:49:52 -0700 Subject: [PATCH 2/4] Reverted unnecessary file change --- qcs-api-client-grpc/src/tonic/channel.rs | 35 +++++------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/qcs-api-client-grpc/src/tonic/channel.rs b/qcs-api-client-grpc/src/tonic/channel.rs index fea027f..1c539a1 100644 --- a/qcs-api-client-grpc/src/tonic/channel.rs +++ b/qcs-api-client-grpc/src/tonic/channel.rs @@ -146,8 +146,6 @@ pub struct ChannelBuilder { endpoint: Endpoint, #[cfg(feature = "tracing")] trace_layer: CustomTraceLayer, - http_proxy: Option, - https_proxy: Option, options: O, } @@ -166,8 +164,6 @@ impl From for ChannelBuilder<()> { #[cfg(not(feature = "tracing"))] return Self { endpoint, - http_proxy: None, - https_proxy: None, options: (), }; } @@ -404,13 +400,9 @@ fn get_uri_socks_auth(uri: &Uri) -> Result, url::ParseError> { /// # Errors /// /// See [`ChannelError`]. -pub fn get_channel( - uri: Uri, - http_proxy: Option, - https_proxy: Option, -) -> Result { +pub fn get_channel(uri: Uri) -> Result { let endpoint = get_endpoint(uri); - get_channel_with_endpoint(&endpoint, http_proxy, https_proxy) + get_channel_with_endpoint(&endpoint) } /// Get a [`Channel`] to the given [`Uri`], with an optional timeout. If set to [`None`], no timeout is @@ -431,12 +423,10 @@ pub fn get_channel( /// See [`ChannelError`]. pub fn get_channel_with_timeout( uri: Uri, - https_proxy: Option, - http_proxy: Option, timeout: Option, ) -> Result { let endpoint = get_endpoint_with_timeout(uri, timeout); - get_channel_with_endpoint(&endpoint, https_proxy, http_proxy) + get_channel_with_endpoint(&endpoint) } /// Get a [`Channel`] to the given [`Endpoint`]. Useful if [`get_channel`] or @@ -458,18 +448,9 @@ pub fn get_channel_with_timeout( /// /// Returns a [`ChannelError`] if the channel cannot be constructed. #[allow(clippy::similar_names)] // http(s)_proxy are similar but precise in this case. -pub fn get_channel_with_endpoint( - endpoint: &Endpoint, - mut https_proxy: Option, - mut http_proxy: Option, -) -> Result { - if https_proxy.is_none() { - https_proxy = get_env_uri("HTTPS_PROXY")?; - } - - if http_proxy.is_none() { - http_proxy = get_env_uri("HTTP_PROXY")?; - } +pub fn get_channel_with_endpoint(endpoint: &Endpoint) -> Result { + let https_proxy = get_env_uri("HTTPS_PROXY")?; + let http_proxy = get_env_uri("HTTP_PROXY")?; let mut connector = HttpConnector::new(); connector.enforce_http(false); @@ -542,10 +523,8 @@ pub fn get_channel_with_endpoint( /// See [`Error`] pub fn get_wrapped_channel( uri: Uri, - https_proxy: Option, - http_proxy: Option, ) -> Result, Error> { - wrap_channel(get_channel(uri, https_proxy, http_proxy)?) + wrap_channel(get_channel(uri)?) } /// Set up the given `channel` with QCS authentication. From 31c7b3899413663af286978d441bad9478b8b534 Mon Sep 17 00:00:00 2001 From: "ryan.dougherty" Date: Thu, 3 Jul 2025 14:50:10 -0700 Subject: [PATCH 3/4] Override get_endpoint to have an increased timeout window and keep alive interval --- qcs-api-client-grpc/src/tonic/channel.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/qcs-api-client-grpc/src/tonic/channel.rs b/qcs-api-client-grpc/src/tonic/channel.rs index 1c539a1..65789ee 100644 --- a/qcs-api-client-grpc/src/tonic/channel.rs +++ b/qcs-api-client-grpc/src/tonic/channel.rs @@ -340,7 +340,10 @@ pub fn parse_uri(s: &str) -> Result> { s.parse().map_err(Error::from) } -/// Get an [`Endpoint`] for the given [`Uri`] +/// Get an [`Endpoint`] for the given [`Uri`] with default settings. +/// This endpoint will default to using a 2 minute timeout, and will +/// keep the connection alive while idle, with a 60 second keep-alive +/// interval. #[allow(clippy::missing_panics_doc)] pub fn get_endpoint(uri: Uri) -> Endpoint { Channel::builder(uri) @@ -351,9 +354,12 @@ pub fn get_endpoint(uri: Uri) -> Endpoint { .expect("user agent string should be valid") .tls_config(ClientTlsConfig::new().with_enabled_roots()) .expect("tls setup should succeed") + .keep_alive_while_idle(true) + .http2_keep_alive_interval(Duration::from_secs(60)) + .timeout(Duration::from_secs(120)) } -/// Get an [`Endpoint`] for the given [`Uri`] and timeout. +/// Get an [`Endpoint`] for the given [`Uri`] and custom timeout duration. pub fn get_endpoint_with_timeout(uri: Uri, timeout: Option) -> Endpoint { if let Some(duration) = timeout { get_endpoint(uri).timeout(duration) From fe0d944d6edded0e1710242071971ea57eeb800c Mon Sep 17 00:00:00 2001 From: "ryan.dougherty" Date: Tue, 8 Jul 2025 15:31:33 -0700 Subject: [PATCH 4/4] Increased http2_keep_alive_interval to 2 minutes --- qcs-api-client-common/src/backoff.rs | 9 +++------ qcs-api-client-grpc/src/tonic/channel.rs | 8 ++++---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/qcs-api-client-common/src/backoff.rs b/qcs-api-client-common/src/backoff.rs index 94157da..0cc5c7f 100644 --- a/qcs-api-client-common/src/backoff.rs +++ b/qcs-api-client-common/src/backoff.rs @@ -12,17 +12,14 @@ pub use ::backoff::*; /// Create a default [`ExponentialBackoff`] for use with QCS. /// -/// This backoff will retry for up to 5 minutes. The initial interval is 30 seconds, -/// and the backoff will double the interval each time it is used, up to the maximum -/// interval of 2 minutes. +/// This backoff will retry for up to 5 minutes, with a maximum interval of 30 seconds and some +/// randomized jitter. #[allow(clippy::module_name_repetitions)] #[must_use] pub fn default_backoff() -> ExponentialBackoff { ExponentialBackoffBuilder::new() .with_max_elapsed_time(Some(Duration::from_secs(300))) - .with_initial_interval(Duration::from_secs(30)) - .with_max_interval(Duration::from_secs(120)) - .with_multiplier(2.0) + .with_max_interval(Duration::from_secs(30)) .build() } diff --git a/qcs-api-client-grpc/src/tonic/channel.rs b/qcs-api-client-grpc/src/tonic/channel.rs index 65789ee..5f1cfb2 100644 --- a/qcs-api-client-grpc/src/tonic/channel.rs +++ b/qcs-api-client-grpc/src/tonic/channel.rs @@ -341,8 +341,8 @@ pub fn parse_uri(s: &str) -> Result> { } /// Get an [`Endpoint`] for the given [`Uri`] with default settings. -/// This endpoint will default to using a 2 minute timeout, and will -/// keep the connection alive while idle, with a 60 second keep-alive +/// This endpoint will default to using a 5 minute timeout, and will +/// keep the connection alive while idle, with a 120 second keep-alive /// interval. #[allow(clippy::missing_panics_doc)] pub fn get_endpoint(uri: Uri) -> Endpoint { @@ -355,8 +355,8 @@ pub fn get_endpoint(uri: Uri) -> Endpoint { .tls_config(ClientTlsConfig::new().with_enabled_roots()) .expect("tls setup should succeed") .keep_alive_while_idle(true) - .http2_keep_alive_interval(Duration::from_secs(60)) - .timeout(Duration::from_secs(120)) + .http2_keep_alive_interval(Duration::from_secs(120)) + .timeout(Duration::from_secs(300)) } /// Get an [`Endpoint`] for the given [`Uri`] and custom timeout duration.