refactor(proxy): enhance proxy state management and refresh logic

This commit is contained in:
Tunglies
2025-06-05 20:10:28 +08:00
parent 44f085604a
commit 80f550d67e
5 changed files with 45 additions and 84 deletions

View File

@@ -7,16 +7,40 @@ use std::{
use tauri::Manager; use tauri::Manager;
const PROVIDERS_REFRESH_INTERVAL: Duration = Duration::from_secs(3); const PROVIDERS_REFRESH_INTERVAL: Duration = Duration::from_secs(3);
const PROXIES_REFRESH_INTERVAL: Duration = Duration::from_secs(1);
#[tauri::command] #[tauri::command]
pub async fn get_proxies() -> CmdResult<serde_json::Value> { pub async fn get_proxies() -> CmdResult<serde_json::Value> {
let manager = MihomoManager::global(); let manager = MihomoManager::global();
manager let app_handle = handle::Handle::global().app_handle().unwrap();
.refresh_proxies() let cmd_proxy_state = app_handle.state::<Mutex<CmdProxyState>>();
.await
.map(|_| manager.get_proxies()) let should_refresh = {
.or_else(|_| Ok(manager.get_proxies())) let mut state = cmd_proxy_state.lock().unwrap();
let now = Instant::now();
if now.duration_since(state.last_refresh_time) > PROXIES_REFRESH_INTERVAL {
state.need_refresh = true;
state.last_refresh_time = now;
}
state.need_refresh
};
if should_refresh {
let proxies = manager.get_refresh_proxies().await?;
{
let mut state = cmd_proxy_state.lock().unwrap();
state.proxies = proxies;
state.need_refresh = false;
}
log::debug!(target: "app", "proxies刷新成功");
}
let proxies = {
let state = cmd_proxy_state.lock().unwrap();
state.proxies.clone()
};
Ok(proxies)
} }
#[tauri::command] #[tauri::command]
@@ -36,14 +60,12 @@ pub async fn get_providers_proxies() -> CmdResult<serde_json::Value> {
if should_refresh { if should_refresh {
let manager = MihomoManager::global(); let manager = MihomoManager::global();
if let Err(e) = manager.refresh_providers_proxies().await { let providers = manager.get_providers_proxies().await?;
log::warn!(target: "app", "providers_proxies刷新失败: {}", e); {
return Err(e.into()); let mut state = cmd_proxy_state.lock().unwrap();
state.providers_proxies = providers;
state.need_refresh = false;
} }
let mut state = cmd_proxy_state.lock().unwrap();
state.providers_proxies = manager.get_providers_proxies().clone();
state.need_refresh = false;
log::debug!(target: "app", "providers_proxies刷新成功"); log::debug!(target: "app", "providers_proxies刷新成功");
} }

View File

@@ -1,6 +1,7 @@
pub struct CmdProxyState { pub struct CmdProxyState {
pub last_refresh_time: std::time::Instant, pub last_refresh_time: std::time::Instant,
pub need_refresh: bool, pub need_refresh: bool,
pub proxies: serde_json::Value,
pub providers_proxies: serde_json::Value, pub providers_proxies: serde_json::Value,
} }
@@ -9,6 +10,7 @@ impl Default for CmdProxyState {
Self { Self {
last_refresh_time: std::time::Instant::now(), last_refresh_time: std::time::Instant::now(),
need_refresh: true, need_refresh: true,
proxies: serde_json::Value::Null,
providers_proxies: serde_json::Value::Null, providers_proxies: serde_json::Value::Null,
} }
} }

View File

@@ -1,11 +1,8 @@
use reqwest::{Method, header::HeaderMap}; use reqwest::{Method, header::HeaderMap};
use serde_json::json; use serde_json::{Value, json};
use std::{ use std::time::Duration;
sync::{Arc, Mutex},
time::Duration,
};
pub mod model; pub mod model;
pub use model::{MihomoData, MihomoManager}; pub use model::MihomoManager;
impl MihomoManager { impl MihomoManager {
pub fn new(mihomo_server: String, headers: HeaderMap) -> Self { pub fn new(mihomo_server: String, headers: HeaderMap) -> Self {
@@ -20,38 +17,10 @@ impl MihomoManager {
Self { Self {
mihomo_server, mihomo_server,
data: Arc::new(Mutex::new(MihomoData {
proxies: serde_json::Value::Null,
providers_proxies: serde_json::Value::Null,
})),
client, client,
} }
} }
fn update_proxies(&self, proxies: serde_json::Value) {
let mut data = self.data.lock().expect("Mutex poisoned");
data.proxies = proxies;
}
fn update_providers_proxies(&self, providers_proxies: serde_json::Value) {
let mut data = self.data.lock().expect("Mutex poisoned");
data.providers_proxies = providers_proxies;
}
pub fn get_mihomo_server(&self) -> String {
self.mihomo_server.clone()
}
pub fn get_proxies(&self) -> serde_json::Value {
let data = self.data.lock().expect("Mutex poisoned");
data.proxies.clone()
}
pub fn get_providers_proxies(&self) -> serde_json::Value {
let data = self.data.lock().expect("Mutex poisoned");
data.providers_proxies.clone()
}
async fn send_request( async fn send_request(
&self, &self,
method: Method, method: Method,
@@ -87,18 +56,16 @@ impl MihomoManager {
Ok(response) Ok(response)
} }
pub async fn refresh_proxies(&self) -> Result<&Self, String> { pub async fn get_refresh_proxies(&self) -> Result<Value, String> {
let url = format!("{}/proxies", self.mihomo_server); let url = format!("{}/proxies", self.mihomo_server);
let proxies = self.send_request(Method::GET, url, None).await?; let proxies = self.send_request(Method::GET, url, None).await?;
self.update_proxies(proxies); Ok(proxies)
Ok(self)
} }
pub async fn refresh_providers_proxies(&self) -> Result<&Self, String> { pub async fn get_providers_proxies(&self) -> Result<Value, String> {
let url = format!("{}/providers/proxies", self.mihomo_server); let url = format!("{}/providers/proxies", self.mihomo_server);
let providers_proxies = self.send_request(Method::GET, url, None).await?; let providers_proxies = self.send_request(Method::GET, url, None).await?;
self.update_providers_proxies(providers_proxies); Ok(providers_proxies)
Ok(self)
} }
pub async fn close_all_connections(&self) -> Result<(), String> { pub async fn close_all_connections(&self) -> Result<(), String> {

View File

@@ -1,14 +1,6 @@
use std::sync::{Arc, Mutex};
pub struct MihomoData {
pub(crate) proxies: serde_json::Value,
pub(crate) providers_proxies: serde_json::Value,
}
#[derive(Clone)] #[derive(Clone)]
pub struct MihomoManager { pub struct MihomoManager {
pub(crate) mihomo_server: String, pub(crate) mihomo_server: String,
pub(crate) data: Arc<Mutex<MihomoData>>,
pub(crate) client: reqwest::Client, pub(crate) client: reqwest::Client,
} }

View File

@@ -1,29 +1,7 @@
use mihomo_api;
use reqwest::header::HeaderMap; use reqwest::header::HeaderMap;
#[test] #[test]
fn test_mihomo_manager_init() { fn test_mihomo_manager_init() {
let manager = mihomo_api::MihomoManager::new("url".into(), HeaderMap::new()); let _ = mihomo_api::MihomoManager::new("url".into(), HeaderMap::new());
assert_eq!(manager.get_proxies(), serde_json::Value::Null); assert_eq!(true, true);
assert_eq!(manager.get_providers_proxies(), serde_json::Value::Null);
}
#[tokio::test]
async fn test_refresh_proxies() {
let manager = mihomo_api::MihomoManager::new("http://127.0.0.1:9097".into(), HeaderMap::new());
let manager = manager.refresh_proxies().await.unwrap();
let proxies = manager.get_proxies();
let providers = manager.get_providers_proxies();
assert_ne!(proxies, serde_json::Value::Null);
assert_eq!(providers, serde_json::Value::Null);
}
#[tokio::test]
async fn test_refresh_providers_proxies() {
let manager = mihomo_api::MihomoManager::new("http://127.0.0.1:9097".into(), HeaderMap::new());
let manager = manager.refresh_providers_proxies().await.unwrap();
let proxies = manager.get_proxies();
let providers = manager.get_providers_proxies();
assert_eq!(proxies, serde_json::Value::Null);
assert_ne!(providers, serde_json::Value::Null);
} }