feat(proxy): implement independent failover queue management

Add a new failover queue system that operates independently from provider
sortIndex, allowing users to configure failover order per app type.

Backend changes:
- Add failover_queue table to schema.rs for persistent storage
- Create dao/failover.rs with CRUD operations for queue management
- Add Tauri commands for queue operations (get, add, remove, reorder, toggle)
- Refactor provider_router.rs select_providers() to use failover queue:
  - Current provider always takes first priority
  - Queue providers ordered by queue_order as fallback
  - Only providers with open circuit breakers are included

Frontend changes:
- Add FailoverQueueItem type to proxy.ts
- Extend failover.ts API with queue management methods
- Add React Query hooks for queue data fetching and mutations
- Create FailoverQueueManager component with drag-and-drop reordering
- Integrate queue management into SettingsPage under "Auto Failover"
- Add i18n translations for zh and en locales
This commit is contained in:
Jason
2025-12-12 16:13:07 +08:00
parent c42a0dccaf
commit 5d424b1383
15 changed files with 1198 additions and 47 deletions
+84
View File
@@ -0,0 +1,84 @@
//! 故障转移队列命令
//!
//! 管理代理模式下的故障转移队列
use crate::database::FailoverQueueItem;
use crate::provider::Provider;
use crate::store::AppState;
/// 获取故障转移队列
#[tauri::command]
pub async fn get_failover_queue(
state: tauri::State<'_, AppState>,
app_type: String,
) -> Result<Vec<FailoverQueueItem>, String> {
state
.db
.get_failover_queue(&app_type)
.map_err(|e| e.to_string())
}
/// 获取可添加到故障转移队列的供应商(不在队列中的)
#[tauri::command]
pub async fn get_available_providers_for_failover(
state: tauri::State<'_, AppState>,
app_type: String,
) -> Result<Vec<Provider>, String> {
state
.db
.get_available_providers_for_failover(&app_type)
.map_err(|e| e.to_string())
}
/// 添加供应商到故障转移队列
#[tauri::command]
pub async fn add_to_failover_queue(
state: tauri::State<'_, AppState>,
app_type: String,
provider_id: String,
) -> Result<(), String> {
state
.db
.add_to_failover_queue(&app_type, &provider_id)
.map_err(|e| e.to_string())
}
/// 从故障转移队列移除供应商
#[tauri::command]
pub async fn remove_from_failover_queue(
state: tauri::State<'_, AppState>,
app_type: String,
provider_id: String,
) -> Result<(), String> {
state
.db
.remove_from_failover_queue(&app_type, &provider_id)
.map_err(|e| e.to_string())
}
/// 重新排序故障转移队列
#[tauri::command]
pub async fn reorder_failover_queue(
state: tauri::State<'_, AppState>,
app_type: String,
provider_ids: Vec<String>,
) -> Result<(), String> {
state
.db
.reorder_failover_queue(&app_type, &provider_ids)
.map_err(|e| e.to_string())
}
/// 设置故障转移队列项的启用状态
#[tauri::command]
pub async fn set_failover_item_enabled(
state: tauri::State<'_, AppState>,
app_type: String,
provider_id: String,
enabled: bool,
) -> Result<(), String> {
state
.db
.set_failover_item_enabled(&app_type, &provider_id, enabled)
.map_err(|e| e.to_string())
}
+2
View File
@@ -3,6 +3,7 @@
mod config;
mod deeplink;
mod env;
mod failover;
mod import_export;
mod mcp;
mod misc;
@@ -18,6 +19,7 @@ mod usage;
pub use config::*;
pub use deeplink::*;
pub use env::*;
pub use failover::*;
pub use import_export::*;
pub use mcp::*;
pub use misc::*;