refactor(health-check): remove per-provider test config

This commit is contained in:
Jason
2026-07-10 13:42:09 +08:00
parent 442799879d
commit 06039540ff
18 changed files with 48 additions and 468 deletions
-23
View File
@@ -303,26 +303,6 @@ pub struct UsageResult {
pub error: Option<String>,
}
/// 供应商单独的连通检测配置
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ProviderTestConfig {
/// 是否启用单独配置(false 时使用全局配置)
#[serde(default)]
pub enabled: bool,
/// 超时时间(秒)
#[serde(rename = "timeoutSecs", skip_serializing_if = "Option::is_none")]
pub timeout_secs: Option<u64>,
/// 降级阈值(毫秒)
#[serde(
rename = "degradedThresholdMs",
skip_serializing_if = "Option::is_none"
)]
pub degraded_threshold_ms: Option<u64>,
/// 最大重试次数
#[serde(rename = "maxRetries", skip_serializing_if = "Option::is_none")]
pub max_retries: Option<u32>,
}
/// 认证绑定来源
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "snake_case")]
@@ -454,9 +434,6 @@ pub struct ProviderMeta {
/// 每月消费限额(USD
#[serde(rename = "limitMonthlyUsd", skip_serializing_if = "Option::is_none")]
pub limit_monthly_usd: Option<String>,
/// 供应商单独的模型测试配置
#[serde(rename = "testConfig", skip_serializing_if = "Option::is_none")]
pub test_config: Option<ProviderTestConfig>,
/// Claude API 格式(仅 Claude 供应商使用)
/// - "anthropic": 原生 Anthropic Messages API,直接透传
/// - "openai_chat": OpenAI Chat Completions 格式,需要转换
+6 -75
View File
@@ -92,19 +92,12 @@ impl StreamCheckService {
config: &StreamCheckConfig,
base_url_override: Option<String>,
) -> Result<StreamCheckResult, AppError> {
let effective = Self::merge_provider_config(provider, config);
let mut last_result: Option<StreamCheckResult> = None;
for attempt in 0..=effective.max_retries {
for attempt in 0..=config.max_retries {
let start = Instant::now();
let result = Self::check_once(
app_type,
provider,
&effective,
base_url_override.clone(),
start,
)
.await?;
let result =
Self::check_once(app_type, provider, config, base_url_override.clone(), start)
.await?;
if result.success {
return Ok(StreamCheckResult {
@@ -114,7 +107,7 @@ impl StreamCheckService {
}
// 仅超时 / abort 类网络抖动值得重试;连接被拒、DNS 失败等立即返回。
if Self::should_retry(&result.message) && attempt < effective.max_retries {
if Self::should_retry(&result.message) && attempt < config.max_retries {
last_result = Some(result);
continue;
}
@@ -132,31 +125,11 @@ impl StreamCheckService {
http_status: None,
model_used: String::new(),
tested_at: chrono::Utc::now().timestamp(),
retry_count: effective.max_retries,
retry_count: config.max_retries,
error_category: None,
}))
}
/// 合并供应商单独配置(`meta.testConfig`,仅当 `enabled`)与全局配置。
fn merge_provider_config(provider: &Provider, global: &StreamCheckConfig) -> StreamCheckConfig {
let tc = provider
.meta
.as_ref()
.and_then(|m| m.test_config.as_ref())
.filter(|tc| tc.enabled);
match tc {
Some(tc) => StreamCheckConfig {
timeout_secs: tc.timeout_secs.unwrap_or(global.timeout_secs),
max_retries: tc.max_retries.unwrap_or(global.max_retries),
degraded_threshold_ms: tc
.degraded_threshold_ms
.unwrap_or(global.degraded_threshold_ms),
},
None => global.clone(),
}
}
/// 单次连通性探测。
async fn check_once(
app_type: &AppType,
@@ -474,48 +447,6 @@ mod tests {
assert_eq!(r.status, HealthStatus::Degraded);
}
#[test]
fn test_merge_provider_config_override_and_default() {
use crate::provider::{ProviderMeta, ProviderTestConfig};
let global = StreamCheckConfig::default();
// 无 testConfig → 用全局
let p = make_provider(serde_json::json!({}));
let merged = StreamCheckService::merge_provider_config(&p, &global);
assert_eq!(merged.timeout_secs, global.timeout_secs);
// testConfig 启用并覆盖部分字段
let mut p2 = make_provider(serde_json::json!({}));
p2.meta = Some(ProviderMeta {
test_config: Some(ProviderTestConfig {
enabled: true,
timeout_secs: Some(20),
degraded_threshold_ms: Some(3000),
max_retries: None,
}),
..Default::default()
});
let merged2 = StreamCheckService::merge_provider_config(&p2, &global);
assert_eq!(merged2.timeout_secs, 20);
assert_eq!(merged2.degraded_threshold_ms, 3000);
assert_eq!(merged2.max_retries, global.max_retries); // 未覆盖 → 全局
// testConfig 存在但未启用 → 忽略,用全局
let mut p3 = make_provider(serde_json::json!({}));
p3.meta = Some(ProviderMeta {
test_config: Some(ProviderTestConfig {
enabled: false,
timeout_secs: Some(99),
degraded_threshold_ms: None,
max_retries: None,
}),
..Default::default()
});
let merged3 = StreamCheckService::merge_provider_config(&p3, &global);
assert_eq!(merged3.timeout_secs, global.timeout_secs);
}
#[test]
fn test_resolve_opencode_base_url_explicit_wins() {
let p = make_provider(serde_json::json!({
-4
View File
@@ -368,9 +368,6 @@ pub struct AppSettings {
pub usage_confirmed: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub usage_dashboard_refresh_interval_ms: Option<u32>,
/// User has confirmed the stream check first-run notice
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stream_check_confirmed: Option<bool>,
/// Whether to show the failover toggle independently on the main page
#[serde(default)]
pub enable_failover_toggle: bool,
@@ -511,7 +508,6 @@ impl Default for AppSettings {
proxy_confirmed: None,
usage_confirmed: None,
usage_dashboard_refresh_interval_ms: None,
stream_check_confirmed: None,
enable_failover_toggle: false,
show_profile_switcher: true,
preserve_codex_official_auth_on_switch: false,