refactor(profile-switch): async post-switch tasks, early lock release, and spawn_blocking for IO

This commit is contained in:
Slinetrac
2025-10-27 11:53:31 +08:00
Unverified
parent 9ab80cd7a4
commit f88e848452
2 changed files with 113 additions and 86 deletions

View File

@@ -135,23 +135,7 @@ pub(super) async fn run_switch_job(
Ok(Ok(machine_result)) => match machine_result {
Ok(cmd_result) => match cmd_result {
Ok(success) => {
handle::Handle::notify_profile_switch_finished(
profile_id.clone(),
success,
notify,
task_id,
);
close_connections_after_switch(&profile_id).await;
if notify && success {
handle::Handle::notice_message("info", "Profile Switched");
}
logging!(
info,
Type::Cmd,
"Profile switch task finished: {} (success={})",
profile_id,
success
);
schedule_post_switch_success(profile_id.clone(), success, notify, task_id);
Ok(success)
}
Err(err) => {
@@ -340,16 +324,24 @@ pub(super) async fn restore_previous_profile(previous: Option<SmartString>) -> C
}
AsyncHandler::spawn(|| async move {
match time::timeout(SAVE_PROFILES_TIMEOUT, profiles_save_file_safe()).await {
Ok(Ok(())) => {}
Ok(Err(e)) => {
logging!(
warn,
Type::Cmd,
"Failed to persist restored configuration asynchronously: {}",
e
);
}
let save_future = AsyncHandler::spawn_blocking(|| {
futures::executor::block_on(async { profiles_save_file_safe().await })
});
match time::timeout(SAVE_PROFILES_TIMEOUT, save_future).await {
Ok(join_res) => match join_res {
Ok(Ok(())) => {}
Ok(Err(err)) => {
logging!(
warn,
Type::Cmd,
"Failed to persist restored configuration asynchronously: {}",
err
);
}
Err(join_err) => {
logging!(warn, Type::Cmd, "Blocking save task failed: {}", join_err);
}
},
Err(_) => {
logging!(
warn,
@@ -393,6 +385,32 @@ async fn close_connections_after_switch(profile_id: &SmartString) {
}
}
fn schedule_close_connections(profile_id: SmartString) {
AsyncHandler::spawn(|| async move {
close_connections_after_switch(&profile_id).await;
});
}
fn schedule_post_switch_success(
profile_id: SmartString,
success: bool,
notify: bool,
task_id: u64,
) {
AsyncHandler::spawn(move || async move {
handle::Handle::notify_profile_switch_finished(
profile_id.clone(),
success,
notify,
task_id,
);
if notify && success {
handle::Handle::notice_message("info", "Profile Switched");
}
schedule_close_connections(profile_id);
});
}
pub(super) fn describe_panic_payload(payload: &(dyn Any + Send)) -> String {
if let Some(message) = payload.downcast_ref::<&str>() {
(*message).to_string()

View File

@@ -4,6 +4,7 @@ use crate::{
config::{Config, IProfiles, profiles::profiles_save_file_safe},
core::{CoreManager, handle, tray::Tray},
logging,
process::AsyncHandler,
utils::logging::Type,
};
use futures::FutureExt;
@@ -316,6 +317,8 @@ impl SwitchStateMachine {
Err(_) => CoreUpdateOutcome::Timeout,
};
self.ctx.release_locks();
Ok(SwitchState::Finalize(outcome))
}
@@ -334,12 +337,18 @@ impl SwitchStateMachine {
"Configuration update succeeded, sequence: {}",
self.ctx.sequence()
);
match time::timeout(CONFIG_APPLY_TIMEOUT, async {
Config::profiles().await.apply();
let apply_result = time::timeout(CONFIG_APPLY_TIMEOUT, async {
AsyncHandler::spawn_blocking(|| {
futures::executor::block_on(async {
Config::profiles().await.apply();
});
})
.await
})
.await
{
Ok(()) => {}
.await;
match apply_result {
Ok(_) => {}
Err(_) => {
logging!(
warn,
@@ -366,64 +375,59 @@ impl SwitchStateMachine {
);
}
match time::timeout(TRAY_UPDATE_TIMEOUT, Tray::global().update_tooltip()).await {
Ok(Ok(())) => {}
Ok(Err(err)) => {
logging!(
warn,
Type::Cmd,
"Failed to update tray tooltip asynchronously: {}",
err
);
}
Err(_) => {
logging!(
warn,
Type::Cmd,
"Updating tray tooltip timed out after {:?}",
TRAY_UPDATE_TIMEOUT
);
}
let update_tooltip = time::timeout(TRAY_UPDATE_TIMEOUT, async {
Tray::global().update_tooltip().await
})
.await;
if update_tooltip.is_err() {
logging!(
warn,
Type::Cmd,
"Updating tray tooltip timed out after {:?}",
TRAY_UPDATE_TIMEOUT
);
} else if let Ok(Err(err)) = update_tooltip {
logging!(
warn,
Type::Cmd,
"Failed to update tray tooltip asynchronously: {}",
err
);
}
match time::timeout(TRAY_UPDATE_TIMEOUT, Tray::global().update_menu()).await {
Ok(Ok(())) => {}
Ok(Err(err)) => {
logging!(
warn,
Type::Cmd,
"Failed to update tray menu asynchronously: {}",
err
);
}
Err(_) => {
logging!(
warn,
Type::Cmd,
"Updating tray menu timed out after {:?}",
TRAY_UPDATE_TIMEOUT
);
}
let update_menu = time::timeout(TRAY_UPDATE_TIMEOUT, async {
Tray::global().update_menu().await
})
.await;
if update_menu.is_err() {
logging!(
warn,
Type::Cmd,
"Updating tray menu timed out after {:?}",
TRAY_UPDATE_TIMEOUT
);
} else if let Ok(Err(err)) = update_menu {
logging!(
warn,
Type::Cmd,
"Failed to update tray menu asynchronously: {}",
err
);
}
match time::timeout(SAVE_PROFILES_TIMEOUT, profiles_save_file_safe()).await {
Ok(Ok(())) => {}
Ok(Err(err)) => {
logging!(
warn,
Type::Cmd,
"Failed to persist configuration file asynchronously: {}",
err
);
}
Err(_) => {
logging!(
warn,
Type::Cmd,
"Persisting configuration file timed out after {:?}",
SAVE_PROFILES_TIMEOUT
);
}
let save_future = AsyncHandler::spawn_blocking(|| {
futures::executor::block_on(async { profiles_save_file_safe().await })
});
if time::timeout(SAVE_PROFILES_TIMEOUT, save_future)
.await
.is_err()
{
logging!(
warn,
Type::Cmd,
"Persisting configuration file timed out after {:?}",
SAVE_PROFILES_TIMEOUT
);
}
if let Some(current) = self.ctx.new_profile_for_event.clone() {
@@ -620,6 +624,11 @@ impl SwitchContext {
),
}
}
fn release_locks(&mut self) {
self.core_guard = None;
self.switch_scope = None;
}
}
enum SwitchState {