From 8d1e87dea541e1e539b8f7d8daad4433052cf4ae Mon Sep 17 00:00:00 2001 From: xiaotianxt Date: Thu, 19 Feb 2026 19:33:26 -0500 Subject: [PATCH] perf(channel): offload provider initialization from async workers --- src/channels/mod.rs | 51 +++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/channels/mod.rs b/src/channels/mod.rs index 94e2589c8..8c29ca4ab 100644 --- a/src/channels/mod.rs +++ b/src/channels/mod.rs @@ -701,13 +701,14 @@ async fn get_or_create_provider( None }; - let provider = providers::create_resilient_provider_with_options( + let provider = create_resilient_provider_nonblocking( provider_name, - defaults.api_key.as_deref(), - api_url, - &defaults.reliability, - &ctx.provider_runtime_options, - )?; + ctx.api_key.clone(), + api_url.map(ToString::to_string), + ctx.reliability.as_ref().clone(), + ctx.provider_runtime_options.clone(), + ) + .await?; let provider: Arc = Arc::from(provider); if let Err(err) = provider.warmup().await { @@ -721,6 +722,27 @@ async fn get_or_create_provider( Ok(Arc::clone(cached)) } +async fn create_resilient_provider_nonblocking( + provider_name: &str, + api_key: Option, + api_url: Option, + reliability: crate::config::ReliabilityConfig, + provider_runtime_options: providers::ProviderRuntimeOptions, +) -> anyhow::Result> { + let provider_name = provider_name.to_string(); + tokio::task::spawn_blocking(move || { + providers::create_resilient_provider_with_options( + &provider_name, + api_key.as_deref(), + api_url.as_deref(), + &reliability, + &provider_runtime_options, + ) + }) + .await + .context("failed to join provider initialization task")? +} + fn build_models_help_response(current: &ChannelRouteSelection, workspace_dir: &Path) -> String { let mut response = String::new(); let _ = writeln!( @@ -2492,13 +2514,16 @@ pub async fn start_channels(config: Config) -> Result<()> { secrets_encrypt: config.secrets.encrypt, reasoning_enabled: config.runtime.reasoning_enabled, }; - let provider: Arc = Arc::from(providers::create_resilient_provider_with_options( - &provider_name, - config.api_key.as_deref(), - config.api_url.as_deref(), - &config.reliability, - &provider_runtime_options, - )?); + let provider: Arc = Arc::from( + create_resilient_provider_nonblocking( + &provider_name, + config.api_key.clone(), + config.api_url.clone(), + config.reliability.clone(), + provider_runtime_options.clone(), + ) + .await?, + ); // Warm up the provider connection pool (TLS handshake, DNS, HTTP/2 setup) // so the first real message doesn't hit a cold-start timeout.