use ra_mcp_domain::types::{InvariantViolation, WorkspaceRoot}; use std::{path::PathBuf, time::Duration}; /// Exponential backoff policy for worker restart attempts. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct BackoffPolicy { /// Minimum delay between restart attempts. pub floor: Duration, /// Maximum delay between restart attempts. pub ceiling: Duration, } impl BackoffPolicy { /// Builds a validated backoff policy. pub fn try_new(floor: Duration, ceiling: Duration) -> Result { if floor.is_zero() { return Err(InvariantViolation::new("backoff floor must be non-zero")); } if ceiling < floor { return Err(InvariantViolation::new( "backoff ceiling must be greater than or equal to floor", )); } Ok(Self { floor, ceiling }) } } /// Runtime engine configuration. #[derive(Debug, Clone, PartialEq, Eq)] pub struct EngineConfig { /// Absolute workspace root used for rust-analyzer process cwd/root URI. pub workspace_root: WorkspaceRoot, /// rust-analyzer executable path. pub rust_analyzer_binary: PathBuf, /// Additional rust-analyzer process arguments. pub rust_analyzer_args: Vec, /// Additional rust-analyzer process environment variables. pub rust_analyzer_env: Vec<(String, String)>, /// Startup handshake timeout. pub startup_timeout: Duration, /// Timeout for ordinary requests. pub request_timeout: Duration, /// Restart backoff policy. pub backoff_policy: BackoffPolicy, } impl EngineConfig { /// Builds validated engine configuration. pub fn try_new( workspace_root: WorkspaceRoot, rust_analyzer_binary: PathBuf, rust_analyzer_args: Vec, rust_analyzer_env: Vec<(String, String)>, startup_timeout: Duration, request_timeout: Duration, backoff_policy: BackoffPolicy, ) -> Result { if rust_analyzer_binary.as_os_str().is_empty() { return Err(InvariantViolation::new( "rust-analyzer binary path must be non-empty", )); } if startup_timeout.is_zero() { return Err(InvariantViolation::new("startup timeout must be non-zero")); } if request_timeout.is_zero() { return Err(InvariantViolation::new("request timeout must be non-zero")); } Ok(Self { workspace_root, rust_analyzer_binary, rust_analyzer_args, rust_analyzer_env, startup_timeout, request_timeout, backoff_policy, }) } }