Files
CC-Switch/src-tauri/src/database/dao/stream_check.rs
T
Jason bf40b0138c feat: add usage daily rollups, incremental auto-vacuum, and sync-aware backup
- Add usage_daily_rollups table (schema v6) to aggregate proxy request
  logs into daily summaries, reducing query overhead for statistics
- Add rollup_and_prune DAO that aggregates old detail logs (>N days)
  into rollup rows and deletes the originals
- Update all usage stats queries to UNION detail logs with rollup data
- Introduce incremental auto-vacuum for SQLite, with startup and
  periodic cleanup of old stream_check_logs and request log rollups
- Split backup export/import into full vs sync variants: WebDAV sync
  now skips local-only table data (proxy_request_logs,
  stream_check_logs, provider_health, proxy_live_backup,
  usage_daily_rollups) while preserving them on import
- Add enable_logging guard to skip request log writes when disabled
- Apply cargo fmt formatting fixes across multiple modules
2026-03-08 19:42:18 +08:00

75 lines
2.7 KiB
Rust

//! 流式健康检查日志 DAO
use crate::database::{lock_conn, Database};
use crate::error::AppError;
use crate::services::stream_check::{StreamCheckConfig, StreamCheckResult};
impl Database {
/// 保存流式检查日志
pub fn save_stream_check_log(
&self,
provider_id: &str,
provider_name: &str,
app_type: &str,
result: &StreamCheckResult,
) -> Result<i64, AppError> {
let conn = lock_conn!(self.conn);
conn.execute(
"INSERT INTO stream_check_logs
(provider_id, provider_name, app_type, status, success, message,
response_time_ms, http_status, model_used, retry_count, tested_at)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)",
rusqlite::params![
provider_id,
provider_name,
app_type,
format!("{:?}", result.status).to_lowercase(),
result.success,
result.message,
result.response_time_ms.map(|t| t as i64),
result.http_status.map(|s| s as i64),
result.model_used,
result.retry_count as i64,
result.tested_at,
],
)
.map_err(|e| AppError::Database(e.to_string()))?;
Ok(conn.last_insert_rowid())
}
/// 获取流式检查配置
pub fn get_stream_check_config(&self) -> Result<StreamCheckConfig, AppError> {
match self.get_setting("stream_check_config")? {
Some(json) => serde_json::from_str(&json)
.map_err(|e| AppError::Message(format!("解析配置失败: {e}"))),
None => Ok(StreamCheckConfig::default()),
}
}
/// Delete stream check logs older than `retain_days` days.
/// Returns the number of deleted rows.
pub fn cleanup_old_stream_check_logs(&self, retain_days: i64) -> Result<u64, AppError> {
let cutoff = chrono::Utc::now().timestamp() - retain_days * 86400;
let conn = lock_conn!(self.conn);
let deleted = conn
.execute(
"DELETE FROM stream_check_logs WHERE tested_at < ?1",
[cutoff],
)
.map_err(|e| AppError::Database(e.to_string()))?;
if deleted > 0 {
log::info!("Cleaned up {deleted} stream_check_logs older than {retain_days} days");
}
Ok(deleted as u64)
}
/// 保存流式检查配置
pub fn save_stream_check_config(&self, config: &StreamCheckConfig) -> Result<(), AppError> {
let json = serde_json::to_string(config)
.map_err(|e| AppError::Message(format!("序列化配置失败: {e}")))?;
self.set_setting("stream_check_config", &json)
}
}