mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-04 19:45:34 +08:00
fix(database): close canonical restore review gaps
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -100,6 +100,23 @@ pub(crate) fn validate_provider_storage_json(
|
|||||||
if let Some(source) = meta.pricing_model_source.as_deref() {
|
if let Some(source) = meta.pricing_model_source.as_deref() {
|
||||||
super::proxy::validate_pricing_source(source)?;
|
super::proxy::validate_pricing_source(source)?;
|
||||||
}
|
}
|
||||||
|
for (field, value) in [
|
||||||
|
("limitDailyUsd", meta.limit_daily_usd.as_deref()),
|
||||||
|
("limitMonthlyUsd", meta.limit_monthly_usd.as_deref()),
|
||||||
|
] {
|
||||||
|
if let Some(value) = value {
|
||||||
|
let parsed = value.parse::<rust_decimal::Decimal>().map_err(|error| {
|
||||||
|
AppError::InvalidInput(format!(
|
||||||
|
"invalid provider meta {field} for '{app_type}/{provider_id}': {error}"
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
if parsed < rust_decimal::Decimal::ZERO {
|
||||||
|
return Err(AppError::InvalidInput(format!(
|
||||||
|
"negative provider meta {field} for '{app_type}/{provider_id}'"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,7 +512,17 @@ impl Database {
|
|||||||
|row| row.get(0),
|
|row| row.get(0),
|
||||||
)
|
)
|
||||||
.map_err(|e| AppError::Database(e.to_string()))?;
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
||||||
Ok(max.map(|v| (v + 1) as usize).unwrap_or(0))
|
match max {
|
||||||
|
Some(value) => value
|
||||||
|
.checked_add(1)
|
||||||
|
.and_then(|next| usize::try_from(next).ok())
|
||||||
|
.ok_or_else(|| {
|
||||||
|
AppError::InvalidInput(format!(
|
||||||
|
"provider sort_index cannot advance past {value}"
|
||||||
|
))
|
||||||
|
}),
|
||||||
|
None => Ok(0),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 启动时调用:补齐缺失的官方预设供应商(Claude / Codex / Gemini)。
|
/// 启动时调用:补齐缺失的官方预设供应商(Claude / Codex / Gemini)。
|
||||||
|
|||||||
@@ -25,9 +25,8 @@ impl Database {
|
|||||||
.map_err(|e| AppError::Database(e.to_string()))?;
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
||||||
|
|
||||||
if let Some(row) = rows.next().map_err(|e| AppError::Database(e.to_string()))? {
|
if let Some(row) = rows.next().map_err(|e| AppError::Database(e.to_string()))? {
|
||||||
Ok(Some(
|
row.get::<_, Option<String>>(0)
|
||||||
row.get(0).map_err(|e| AppError::Database(e.to_string()))?,
|
.map_err(|e| AppError::Database(e.to_string()))
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@@ -325,3 +324,23 @@ impl Database {
|
|||||||
self.set_setting("log_config", &json)
|
self.set_setting("log_config", &json)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::database::{lock_conn, Database};
|
||||||
|
use crate::error::AppError;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn null_setting_value_hydrates_as_absent() -> Result<(), crate::error::AppError> {
|
||||||
|
let database = Database::memory()?;
|
||||||
|
{
|
||||||
|
let conn = lock_conn!(database.conn);
|
||||||
|
conn.execute(
|
||||||
|
"INSERT INTO settings (key, value) VALUES ('nullable-setting', NULL)",
|
||||||
|
[],
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
assert_eq!(database.get_setting("nullable-setting")?, None);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -7,7 +7,7 @@
|
|||||||
"binaryRestoreBytes": 2147483648,
|
"binaryRestoreBytes": 2147483648,
|
||||||
"scratchBytes": 2147483648
|
"scratchBytes": 2147483648
|
||||||
},
|
},
|
||||||
"specSha256": "e2b44f6fbbb1ca7287487e68aeb5684853c024978f418be688fcd15d665fd3aa",
|
"specSha256": "f5f04260bd45bc2cd6f4766d2c66f445dad685766c1950872bc626262f113907",
|
||||||
"tables": [
|
"tables": [
|
||||||
{"name": "providers", "policy": "portable_incoming"},
|
{"name": "providers", "policy": "portable_incoming"},
|
||||||
{"name": "provider_endpoints", "policy": "portable_incoming"},
|
{"name": "provider_endpoints", "policy": "portable_incoming"},
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
{"name": "stream_check_logs", "policy": "portable_incoming"},
|
{"name": "stream_check_logs", "policy": "portable_incoming"},
|
||||||
{"name": "proxy_live_backup", "policy": "portable_incoming"},
|
{"name": "proxy_live_backup", "policy": "portable_incoming"},
|
||||||
{"name": "usage_daily_rollups", "policy": "portable_incoming"},
|
{"name": "usage_daily_rollups", "policy": "portable_incoming"},
|
||||||
{"name": "session_log_sync", "policy": "portable_incoming"},
|
{"name": "session_log_sync", "policy": "preserve_live"},
|
||||||
{"name": "profiles", "policy": "portable_incoming"},
|
{"name": "profiles", "policy": "portable_incoming"},
|
||||||
{"name": "pi_provider_projections", "policy": "preserve_live"},
|
{"name": "pi_provider_projections", "policy": "preserve_live"},
|
||||||
{"name": "skill_deployments", "policy": "preserve_live"}
|
{"name": "skill_deployments", "policy": "preserve_live"}
|
||||||
|
|||||||
Reference in New Issue
Block a user