mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-25 13:45:03 +08:00
1126c7459d
* style(FailoverQueueManager): 显示供应商备注信息 * style(FailoverQueueItem): 添加供应商备注字段以支持备注信息显示 * style(FailoverQueueManager): 显示供应商备注信息 * style(FailoverQueueItem): 添加供应商备注字段以支持备注信息显示 * style(FailoverQueueManager): 更新供应商备注信息的显示样式 * style(FailoverQueueItem): 添加条件序列化以优化供应商备注字段
150 lines
4.8 KiB
Rust
150 lines
4.8 KiB
Rust
//! 故障转移队列 DAO
|
|
//!
|
|
//! 管理代理模式下的故障转移队列(基于 providers 表的 in_failover_queue 字段)
|
|
|
|
use crate::database::{lock_conn, Database};
|
|
use crate::error::AppError;
|
|
use crate::provider::Provider;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// 故障转移队列条目(简化版,用于前端展示)
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct FailoverQueueItem {
|
|
pub provider_id: String,
|
|
pub provider_name: String,
|
|
pub sort_index: Option<usize>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub provider_notes: Option<String>,
|
|
}
|
|
|
|
impl Database {
|
|
/// 获取故障转移队列(按 sort_index 排序)
|
|
pub fn get_failover_queue(&self, app_type: &str) -> Result<Vec<FailoverQueueItem>, AppError> {
|
|
let conn = lock_conn!(self.conn);
|
|
|
|
let mut stmt = conn
|
|
.prepare(
|
|
"SELECT id, name, sort_index, notes
|
|
FROM providers
|
|
WHERE app_type = ?1 AND in_failover_queue = 1
|
|
ORDER BY COALESCE(sort_index, 999999), id ASC",
|
|
)
|
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
|
|
|
let items = stmt
|
|
.query_map([app_type], |row| {
|
|
Ok(FailoverQueueItem {
|
|
provider_id: row.get(0)?,
|
|
provider_name: row.get(1)?,
|
|
sort_index: row.get(2)?,
|
|
provider_notes: row.get(3)?,
|
|
})
|
|
})
|
|
.map_err(|e| AppError::Database(e.to_string()))?
|
|
.collect::<Result<Vec<_>, _>>()
|
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
|
|
|
Ok(items)
|
|
}
|
|
|
|
/// 获取故障转移队列中的供应商(完整 Provider 信息,按顺序)
|
|
pub fn get_failover_providers(&self, app_type: &str) -> Result<Vec<Provider>, AppError> {
|
|
let all_providers = self.get_all_providers(app_type)?;
|
|
|
|
let result: Vec<Provider> = all_providers
|
|
.into_values()
|
|
.filter(|p| p.in_failover_queue)
|
|
.collect();
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
/// 添加供应商到故障转移队列
|
|
pub fn add_to_failover_queue(&self, app_type: &str, provider_id: &str) -> Result<(), AppError> {
|
|
let conn = lock_conn!(self.conn);
|
|
|
|
conn.execute(
|
|
"UPDATE providers SET in_failover_queue = 1 WHERE id = ?1 AND app_type = ?2",
|
|
rusqlite::params![provider_id, app_type],
|
|
)
|
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 从故障转移队列中移除供应商
|
|
pub fn remove_from_failover_queue(
|
|
&self,
|
|
app_type: &str,
|
|
provider_id: &str,
|
|
) -> Result<(), AppError> {
|
|
let conn = lock_conn!(self.conn);
|
|
|
|
// 1. 从队列中移除
|
|
conn.execute(
|
|
"UPDATE providers SET in_failover_queue = 0 WHERE id = ?1 AND app_type = ?2",
|
|
rusqlite::params![provider_id, app_type],
|
|
)
|
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
|
|
|
// 2. 清除该供应商的健康状态(退出队列后不再需要健康监控)
|
|
conn.execute(
|
|
"DELETE FROM provider_health WHERE provider_id = ?1 AND app_type = ?2",
|
|
rusqlite::params![provider_id, app_type],
|
|
)
|
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
|
|
|
log::info!("已从故障转移队列移除供应商 {provider_id} ({app_type}), 并清除其健康状态");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 清空故障转移队列
|
|
pub fn clear_failover_queue(&self, app_type: &str) -> Result<(), AppError> {
|
|
let conn = lock_conn!(self.conn);
|
|
|
|
conn.execute(
|
|
"UPDATE providers SET in_failover_queue = 0 WHERE app_type = ?1",
|
|
[app_type],
|
|
)
|
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 检查供应商是否在故障转移队列中
|
|
pub fn is_in_failover_queue(
|
|
&self,
|
|
app_type: &str,
|
|
provider_id: &str,
|
|
) -> Result<bool, AppError> {
|
|
let conn = lock_conn!(self.conn);
|
|
|
|
let in_queue: bool = conn
|
|
.query_row(
|
|
"SELECT in_failover_queue FROM providers WHERE id = ?1 AND app_type = ?2",
|
|
rusqlite::params![provider_id, app_type],
|
|
|row| row.get(0),
|
|
)
|
|
.unwrap_or(false);
|
|
|
|
Ok(in_queue)
|
|
}
|
|
|
|
/// 获取可添加到故障转移队列的供应商(不在队列中的)
|
|
pub fn get_available_providers_for_failover(
|
|
&self,
|
|
app_type: &str,
|
|
) -> Result<Vec<Provider>, AppError> {
|
|
let all_providers = self.get_all_providers(app_type)?;
|
|
|
|
let available: Vec<Provider> = all_providers
|
|
.into_values()
|
|
.filter(|p| !p.in_failover_queue)
|
|
.collect();
|
|
|
|
Ok(available)
|
|
}
|
|
}
|