mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-04 03:32:25 +08:00
refactor(provider): certify typed write ownership
Freeze prerequisite A as a component-level certification unit. Add the immutable v5 certification suite, split create/update row DTOs, preserve immutable creation time, map strict-create races to AppError::Conflict, make aggregate compensation insert-or-restore, and enforce reconcile preconditions through a single-lock transaction primitive. Old save_provider callsite classification remains exhaustively recorded in 4f78451405575158ff6562c7021c7f31f2860780; this checkpoint does not add or reclassify an omitted legacy callsite. It tightens the remaining reconciliation classifications there: default live import is [create]; OpenCode/OpenClaw/Hermes existing branches are [update] and absent branches are [create]; universal Claude/Codex/Gemini branches are [create/update] selected from an observed fingerprint. The sealed compensation helper remains the only [restore] path. The old reconcile_provider_record symbol is deleted. Remaining update_provider_settings_config callsites are classified as [update]: codex_history_migration updates an already-read Codex row; proxy token synchronization updates already-read Claude, Codex, Gemini, and GrokBuild rows. Each now uses ProviderKey plus ProviderRowUpdate, explicitly removes hydrated endpoint projections, preserves endpoint authority, and fails on a missing row instead of silently succeeding.
This commit is contained in:
@@ -4,13 +4,14 @@
|
||||
|
||||
use crate::app_config::AppType;
|
||||
use crate::config::{get_claude_settings_path, read_json_file, write_json_file};
|
||||
use crate::database::Database;
|
||||
use crate::database::{Database, ProviderKey, ProviderRowUpdate};
|
||||
use crate::provider::Provider;
|
||||
use crate::proxy::server::ProxyServer;
|
||||
use crate::proxy::switch_lock::SwitchLockManager;
|
||||
use crate::proxy::types::*;
|
||||
use crate::services::provider::{
|
||||
build_effective_settings_with_common_config, write_live_with_common_config,
|
||||
build_effective_settings_with_common_config, provider_to_mutation_input,
|
||||
write_live_with_common_config,
|
||||
};
|
||||
use serde_json::{json, Map, Value};
|
||||
use std::str::FromStr;
|
||||
@@ -1055,11 +1056,16 @@ impl ProxyService {
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = self.db.update_provider_settings_config(
|
||||
"claude",
|
||||
&provider_id,
|
||||
&provider.settings_config,
|
||||
) {
|
||||
if let Some(meta) = provider.meta.as_mut() {
|
||||
meta.custom_endpoints.clear();
|
||||
}
|
||||
let input = provider_to_mutation_input(provider);
|
||||
let result =
|
||||
ProviderKey::new("claude", &provider_id).and_then(|key| {
|
||||
let row = ProviderRowUpdate::from_input(&input)?;
|
||||
self.db.update_provider(&key, &row)
|
||||
});
|
||||
if let Err(e) = result {
|
||||
log::warn!("同步 Claude Token 到数据库失败: {e}");
|
||||
} else {
|
||||
log::info!(
|
||||
@@ -1116,11 +1122,15 @@ impl ProxyService {
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = self.db.update_provider_settings_config(
|
||||
"codex",
|
||||
&provider_id,
|
||||
&provider.settings_config,
|
||||
) {
|
||||
if let Some(meta) = provider.meta.as_mut() {
|
||||
meta.custom_endpoints.clear();
|
||||
}
|
||||
let input = provider_to_mutation_input(provider);
|
||||
let result = ProviderKey::new("codex", &provider_id).and_then(|key| {
|
||||
let row = ProviderRowUpdate::from_input(&input)?;
|
||||
self.db.update_provider(&key, &row)
|
||||
});
|
||||
if let Err(e) = result {
|
||||
log::warn!("同步 Codex Token 到数据库失败: {e}");
|
||||
} else {
|
||||
log::info!("已同步 Codex Token 到数据库 (provider: {provider_id})");
|
||||
@@ -1168,11 +1178,15 @@ impl ProxyService {
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = self.db.update_provider_settings_config(
|
||||
"gemini",
|
||||
&provider_id,
|
||||
&provider.settings_config,
|
||||
) {
|
||||
if let Some(meta) = provider.meta.as_mut() {
|
||||
meta.custom_endpoints.clear();
|
||||
}
|
||||
let input = provider_to_mutation_input(provider);
|
||||
let result = ProviderKey::new("gemini", &provider_id).and_then(|key| {
|
||||
let row = ProviderRowUpdate::from_input(&input)?;
|
||||
self.db.update_provider(&key, &row)
|
||||
});
|
||||
if let Err(e) = result {
|
||||
log::warn!("同步 Gemini Token 到数据库失败: {e}");
|
||||
} else {
|
||||
log::info!(
|
||||
@@ -1211,15 +1225,20 @@ impl ProxyService {
|
||||
format!("更新 Grok Build API Key 失败: {e}")
|
||||
})?;
|
||||
provider.settings_config["config"] = json!(updated);
|
||||
self.db
|
||||
.update_provider_settings_config(
|
||||
"grokbuild",
|
||||
&provider_id,
|
||||
&provider.settings_config,
|
||||
)
|
||||
.map_err(|e| {
|
||||
if let Some(meta) = provider.meta.as_mut() {
|
||||
meta.custom_endpoints.clear();
|
||||
}
|
||||
let input = provider_to_mutation_input(provider);
|
||||
let key = ProviderKey::new("grokbuild", &provider_id).map_err(
|
||||
|e| format!("同步 Grok Build Token 到数据库失败: {e}"),
|
||||
)?;
|
||||
let row =
|
||||
ProviderRowUpdate::from_input(&input).map_err(|e| {
|
||||
format!("同步 Grok Build Token 到数据库失败: {e}")
|
||||
})?;
|
||||
self.db.update_provider(&key, &row).map_err(|e| {
|
||||
format!("同步 Grok Build Token 到数据库失败: {e}")
|
||||
})?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user