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

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

View File

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

View File

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

View File

@@ -1,11 +1,8 @@
use reqwest::{Method, header::HeaderMap};
use serde_json::json;
use std::{
sync::{Arc, Mutex},
time::Duration,
};
use serde_json::{Value, json};
use std::time::Duration;
pub mod model;
pub use model::{MihomoData, MihomoManager};
pub use model::MihomoManager;
impl MihomoManager {
pub fn new(mihomo_server: String, headers: HeaderMap) -> Self {
@@ -20,38 +17,10 @@ impl MihomoManager {
Self {
mihomo_server,
data: Arc::new(Mutex::new(MihomoData {
proxies: serde_json::Value::Null,
providers_proxies: serde_json::Value::Null,
})),
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(
&self,
method: Method,
@@ -87,18 +56,16 @@ impl MihomoManager {
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 proxies = self.send_request(Method::GET, url, None).await?;
self.update_proxies(proxies);
Ok(self)
Ok(proxies)
}
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 providers_proxies = self.send_request(Method::GET, url, None).await?;
self.update_providers_proxies(providers_proxies);
Ok(self)
Ok(providers_proxies)
}
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)]
pub struct MihomoManager {
pub(crate) mihomo_server: String,
pub(crate) data: Arc<Mutex<MihomoData>>,
pub(crate) client: reqwest::Client,
}

View File

@@ -1,29 +1,7 @@
use mihomo_api;
use reqwest::header::HeaderMap;
#[test]
fn test_mihomo_manager_init() {
let manager = mihomo_api::MihomoManager::new("url".into(), HeaderMap::new());
assert_eq!(manager.get_proxies(), serde_json::Value::Null);
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);
let _ = mihomo_api::MihomoManager::new("url".into(), HeaderMap::new());
assert_eq!(true, true);
}