Add AsyncHandler for wrapping task spawning

This commit is contained in:
Tunglies 2025-04-11 17:27:56 +08:00
parent 644fdc071f
commit b6a6f5f434
12 changed files with 82 additions and 52 deletions

View File

@ -3,6 +3,7 @@ use crate::{
config::PrfItem, config::PrfItem,
core::{handle, CoreManager}, core::{handle, CoreManager},
enhance, logging, enhance, logging,
process::AsyncHandler,
utils::{dirs, help, logging::Type}, utils::{dirs, help, logging::Type},
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@ -117,7 +118,7 @@ impl Config {
// 在单独的任务中发送通知 // 在单独的任务中发送通知
if let Some((msg_type, msg_content)) = validation_result { if let Some((msg_type, msg_content)) = validation_result {
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(move || async move {
sleep(Duration::from_secs(2)).await; sleep(Duration::from_secs(2)).await;
handle::Handle::notice_message(msg_type, &msg_content); handle::Handle::notice_message(msg_type, &msg_content);
}); });

View File

@ -3,7 +3,7 @@ use parking_lot::RwLock;
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use tauri::{AppHandle, Emitter, Manager, WebviewWindow}; use tauri::{AppHandle, Emitter, Manager, WebviewWindow};
use crate::{logging, logging_error, utils::logging::Type}; use crate::{logging, logging_error, process::AsyncHandler, utils::logging::Type};
/// 存储启动期间的错误消息 /// 存储启动期间的错误消息
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -152,7 +152,7 @@ impl Handle {
let window_clone = window.clone(); let window_clone = window.clone();
let errors_clone = errors.clone(); let errors_clone = errors.clone();
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(move || async move {
tokio::time::sleep(Duration::from_secs(2)).await; tokio::time::sleep(Duration::from_secs(2)).await;
for error in errors_clone { for error in errors_clone {

View File

@ -2,6 +2,7 @@ use crate::{
config::{Config, IVerge}, config::{Config, IVerge},
core::handle::Handle, core::handle::Handle,
logging, logging_error, logging, logging_error,
process::AsyncHandler,
utils::logging::Type, utils::logging::Type,
}; };
use anyhow::Result; use anyhow::Result;
@ -248,7 +249,7 @@ impl Sysopt {
fn guard_proxy(&self) { fn guard_proxy(&self) {
let _lock = self.guard_state.lock(); let _lock = self.guard_state.lock();
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(move || async move {
// default duration is 10s // default duration is 10s
let mut wait_secs = 10u64; let mut wait_secs = 10u64;

View File

@ -7,6 +7,7 @@ use crate::{
config::Config, config::Config,
feat, feat,
module::{lightweight::entry_lightweight_mode, mihomo::Rate}, module::{lightweight::entry_lightweight_mode, mihomo::Rate},
process::AsyncHandler,
resolve, resolve,
utils::{dirs::find_target_icons, i18n::t, logging::Type, resolve::VERSION}, utils::{dirs::find_target_icons, i18n::t, logging::Type, resolve::VERSION},
}; };
@ -386,42 +387,46 @@ impl Tray {
let speed_rate = Arc::clone(&self.speed_rate); let speed_rate = Arc::clone(&self.speed_rate);
let is_subscribed = Arc::clone(&self.is_subscribed); let is_subscribed = Arc::clone(&self.is_subscribed);
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(move || {
let mut shutdown = shutdown_rx; let mut shutdown = shutdown_rx;
let speed_rate = speed_rate.clone(); // 确保 Arc 被正确克隆
let is_subscribed = is_subscribed.clone();
'outer: loop { Box::pin(async move {
match Traffic::get_traffic_stream().await { 'outer: loop {
Ok(mut stream) => loop { match Traffic::get_traffic_stream().await {
tokio::select! { Ok(mut stream) => loop {
Some(traffic) = stream.next() => { tokio::select! {
if let Ok(traffic) = traffic { Some(traffic) = stream.next() => {
let guard = speed_rate.lock(); if let Ok(traffic) = traffic {
let enable_tray_speed: bool = Config::verge().latest().enable_tray_speed.unwrap_or(true); let guard = speed_rate.lock();
if !enable_tray_speed { let enable_tray_speed: bool = Config::verge()
continue; .latest()
} .enable_tray_speed
if let Some(sr) = guard.as_ref() { .unwrap_or(true);
if let Some(rate) = sr.update_and_check_changed(traffic.up, traffic.down) { if !enable_tray_speed {
let _ = Tray::global().update_icon(Some(rate)); continue;
}
if let Some(sr) = guard.as_ref() {
if let Some(rate) = sr.update_and_check_changed(traffic.up, traffic.down) {
let _ = Tray::global().update_icon(Some(rate));
}
} }
} }
} }
_ = shutdown.recv() => break 'outer,
}
},
Err(e) => {
log::error!(target: "app", "Failed to get traffic stream: {}", e);
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
if !*is_subscribed.read() {
break;
} }
_ = shutdown.recv() => break 'outer,
}
},
Err(e) => {
log::error!(target: "app", "Failed to get traffic stream: {}", e);
// 如果获取流失败,等待一段时间后重试
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
// 检查是否应该继续重试
if !*is_subscribed.read() {
break;
} }
} }
} }
} })
}); });
Ok(()) Ok(())

View File

@ -3,6 +3,7 @@ use crate::{
core::{handle, tray, CoreManager}, core::{handle, tray, CoreManager},
logging_error, logging_error,
module::mihomo::MihomoManager, module::mihomo::MihomoManager,
process::AsyncHandler,
utils::{logging::Type, resolve}, utils::{logging::Type, resolve},
}; };
use serde_yaml::{Mapping, Value}; use serde_yaml::{Mapping, Value};
@ -10,7 +11,7 @@ use tauri::Manager;
/// Restart the Clash core /// Restart the Clash core
pub fn restart_clash_core() { pub fn restart_clash_core() {
tauri::async_runtime::spawn(async { AsyncHandler::spawn(move || async move {
match CoreManager::global().restart_core().await { match CoreManager::global().restart_core().await {
Ok(_) => { Ok(_) => {
handle::Handle::refresh_clash(); handle::Handle::refresh_clash();
@ -26,19 +27,17 @@ pub fn restart_clash_core() {
/// Restart the application /// Restart the application
pub fn restart_app() { pub fn restart_app() {
tauri::async_runtime::spawn_blocking(|| { AsyncHandler::spawn(move || async move {
tauri::async_runtime::block_on(async { logging_error!(Type::Core, true, CoreManager::global().stop_core().await);
logging_error!(Type::Core, true, CoreManager::global().stop_core().await); resolve::resolve_reset_async().await;
resolve::resolve_reset_async().await; let app_handle = handle::Handle::global().app_handle().unwrap();
let app_handle = handle::Handle::global().app_handle().unwrap(); std::thread::sleep(std::time::Duration::from_secs(1));
std::thread::sleep(std::time::Duration::from_secs(1)); tauri::process::restart(&app_handle.env());
tauri::process::restart(&app_handle.env());
});
}); });
} }
fn after_change_clash_mode() { fn after_change_clash_mode() {
tauri::async_runtime::spawn(async { AsyncHandler::spawn(move || async {
match MihomoManager::global().get_connections().await { match MihomoManager::global().get_connections().await {
Ok(connections) => { Ok(connections) => {
if let Some(connections_array) = connections["connections"].as_array() { if let Some(connections_array) = connections["connections"].as_array() {
@ -64,7 +63,7 @@ pub fn change_clash_mode(mode: String) {
let json_value = serde_json::json!({ let json_value = serde_json::json!({
"mode": mode "mode": mode
}); });
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(move || async move {
log::debug!(target: "app", "change clash mode to {mode}"); log::debug!(target: "app", "change clash mode to {mode}");
match MihomoManager::global().patch_configs(json_value).await { match MihomoManager::global().patch_configs(json_value).await {
Ok(_) => { Ok(_) => {

View File

@ -2,12 +2,13 @@ use crate::{
cmd, cmd,
config::{Config, PrfItem, PrfOption}, config::{Config, PrfItem, PrfOption},
core::{handle, CoreManager, *}, core::{handle, CoreManager, *},
process::AsyncHandler,
}; };
use anyhow::{bail, Result}; use anyhow::{bail, Result};
/// Toggle proxy profile /// Toggle proxy profile
pub fn toggle_proxy_profile(profile_index: String) { pub fn toggle_proxy_profile(profile_index: String) {
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(|| async move {
let app_handle = handle::Handle::global().app_handle().unwrap(); let app_handle = handle::Handle::global().app_handle().unwrap();
match cmd::patch_profiles_config_by_profile_index(app_handle, profile_index).await { match cmd::patch_profiles_config_by_profile_index(app_handle, profile_index).await {
Ok(_) => { Ok(_) => {

View File

@ -1,6 +1,7 @@
use crate::{ use crate::{
config::{Config, IVerge}, config::{Config, IVerge},
core::handle, core::handle,
process::AsyncHandler,
}; };
use std::env; use std::env;
use tauri_plugin_clipboard_manager::ClipboardExt; use tauri_plugin_clipboard_manager::ClipboardExt;
@ -10,7 +11,7 @@ pub fn toggle_system_proxy() {
let enable = Config::verge().draft().enable_system_proxy; let enable = Config::verge().draft().enable_system_proxy;
let enable = enable.unwrap_or(false); let enable = enable.unwrap_or(false);
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(move || async move {
match super::patch_verge( match super::patch_verge(
IVerge { IVerge {
enable_system_proxy: Some(!enable), enable_system_proxy: Some(!enable),
@ -28,7 +29,7 @@ pub fn toggle_system_proxy() {
/// Toggle TUN mode on/off /// Toggle TUN mode on/off
pub fn toggle_tun_mode(not_save_file: Option<bool>) { pub fn toggle_tun_mode(not_save_file: Option<bool>) {
// tauri::async_runtime::spawn(async move { // AsyncHandler::spawn(async {
// logging!( // logging!(
// info, // info,
// Type::Service, // Type::Service,
@ -44,7 +45,7 @@ pub fn toggle_tun_mode(not_save_file: Option<bool>) {
let enable = Config::verge().data().enable_tun_mode; let enable = Config::verge().data().enable_tun_mode;
let enable = enable.unwrap_or(false); let enable = enable.unwrap_or(false);
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(async move || {
match super::patch_verge( match super::patch_verge(
IVerge { IVerge {
enable_tun_mode: Some(!enable), enable_tun_mode: Some(!enable),

View File

@ -5,9 +5,11 @@ mod enhance;
mod error; mod error;
mod feat; mod feat;
mod module; mod module;
mod process;
mod utils; mod utils;
use crate::{ use crate::{
core::hotkey, core::hotkey,
process::AsyncHandler,
utils::{resolve, resolve::resolve_scheme, server}, utils::{resolve, resolve::resolve_scheme, server},
}; };
use config::Config; use config::Config;
@ -121,11 +123,13 @@ pub fn run() {
use tauri_plugin_deep_link::DeepLinkExt; use tauri_plugin_deep_link::DeepLinkExt;
logging_error!(Type::System, true, app.deep_link().register_all()); logging_error!(Type::System, true, app.deep_link().register_all());
} }
app.deep_link().on_open_url(|event| { app.deep_link().on_open_url(|event| {
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(move || {
if let Some(url) = event.urls().first() { let url = event.urls().first().map(|u| u.to_string());
logging_error!(Type::Setup, true, resolve_scheme(url.to_string()).await); async move {
if let Some(url) = url {
logging_error!(Type::Setup, true, resolve_scheme(url).await);
}
} }
}); });
}); });

View File

@ -0,0 +1,14 @@
use std::future::Future;
use tauri::{async_runtime, async_runtime::JoinHandle};
pub struct AsyncHandler;
impl AsyncHandler {
pub fn spawn<F, Fut>(f: F) -> JoinHandle<()>
where
F: FnOnce() -> Fut + Send + 'static,
Fut: Future<Output = ()> + Send + 'static,
{
async_runtime::spawn(f())
}
}

View File

@ -0,0 +1,2 @@
mod async_handler;
pub use async_handler::AsyncHandler;

View File

@ -5,6 +5,7 @@ use crate::{
core::*, core::*,
logging, logging_error, logging, logging_error,
module::lightweight, module::lightweight,
process::AsyncHandler,
utils::{error, init, logging::Type, server}, utils::{error, init, logging::Type, server},
wrap_err, wrap_err,
}; };
@ -211,7 +212,7 @@ pub fn create_window(is_showup: bool) {
// 标记前端UI已准备就绪向前端发送启动完成事件 // 标记前端UI已准备就绪向前端发送启动完成事件
let app_handle_clone = app_handle.clone(); let app_handle_clone = app_handle.clone();
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(move || async move {
use tauri::Emitter; use tauri::Emitter;
logging!(info, Type::Window, true, "UI gets ready."); logging!(info, Type::Window, true, "UI gets ready.");

View File

@ -4,6 +4,7 @@ use super::resolve;
use crate::{ use crate::{
config::{Config, IVerge, DEFAULT_PAC}, config::{Config, IVerge, DEFAULT_PAC},
logging_error, logging_error,
process::AsyncHandler,
utils::logging::Type, utils::logging::Type,
}; };
use anyhow::{bail, Result}; use anyhow::{bail, Result};
@ -47,7 +48,7 @@ pub async fn check_singleton() -> Result<()> {
pub fn embed_server() { pub fn embed_server() {
let port = IVerge::get_singleton_port(); let port = IVerge::get_singleton_port();
tauri::async_runtime::spawn(async move { AsyncHandler::spawn(move || async move {
let visible = warp::path!("commands" / "visible").map(move || { let visible = warp::path!("commands" / "visible").map(move || {
resolve::create_window(false); resolve::create_window(false);
"ok" "ok"