Skip to content

Commit 9f29fc5

Browse files
authored
fix: stop backend before tray quit exits (#127)
* chore: ignore local task plans * fix: stop backend before tray quit exits * refactor: share backend exit cleanup flow * fix: satisfy clippy test module ordering
1 parent 7a7ff3c commit 9f29fc5

4 files changed

Lines changed: 70 additions & 29 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ runtime/
1010
# generated resources
1111
resources/backend/
1212
resources/webui/
13+
docs/plans/
1314

1415
# rust/tauri build outputs
1516
src-tauri/target/

src-tauri/src/lifecycle/cleanup.rs

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@ use crate::BackendState;
44
pub enum ExitTrigger {
55
ExitRequested,
66
ExitFallback,
7+
TrayQuit,
8+
}
9+
10+
fn duplicate_cleanup_message(trigger: ExitTrigger) -> &'static str {
11+
match trigger {
12+
ExitTrigger::ExitRequested => "exit requested while backend cleanup is already running",
13+
ExitTrigger::ExitFallback => {
14+
"exit fallback cleanup skipped: backend cleanup already running"
15+
}
16+
ExitTrigger::TrayQuit => "tray quit while backend cleanup is already running",
17+
}
18+
}
19+
20+
fn stop_failure_prefix(trigger: ExitTrigger) -> &'static str {
21+
match trigger {
22+
ExitTrigger::ExitRequested => "backend graceful stop on ExitRequested failed",
23+
ExitTrigger::ExitFallback => "backend fallback stop on Exit failed",
24+
ExitTrigger::TrayQuit => "backend graceful stop on tray quit failed",
25+
}
726
}
827

928
pub fn try_begin_exit_cleanup<F>(state: &BackendState, trigger: ExitTrigger, log: F) -> bool
@@ -14,29 +33,41 @@ where
1433
return true;
1534
}
1635

17-
let message = match trigger {
18-
ExitTrigger::ExitRequested => "exit requested while backend cleanup is already running",
19-
ExitTrigger::ExitFallback => {
20-
"exit fallback cleanup skipped: backend cleanup already running"
21-
}
22-
};
23-
log(message);
36+
log(duplicate_cleanup_message(trigger));
2437
false
2538
}
2639

2740
pub fn stop_backend_for_exit<F>(state: &BackendState, trigger: ExitTrigger, log: F)
2841
where
2942
F: Fn(&str),
3043
{
31-
let stop_failure_prefix = match trigger {
32-
ExitTrigger::ExitRequested => "backend graceful stop on ExitRequested failed",
33-
ExitTrigger::ExitFallback => "backend fallback stop on Exit failed",
34-
};
44+
let failure_prefix = stop_failure_prefix(trigger);
3545
if let Err(error) = state.stop_backend() {
36-
log(&format!("{stop_failure_prefix}: {error}"));
46+
log(&format!("{failure_prefix}: {error}"));
3747
}
3848

39-
if matches!(trigger, ExitTrigger::ExitRequested) {
49+
if matches!(trigger, ExitTrigger::ExitRequested | ExitTrigger::TrayQuit) {
4050
log("backend stop finished, exiting desktop process");
4151
}
4252
}
53+
54+
#[cfg(test)]
55+
mod tests {
56+
use super::{duplicate_cleanup_message, ExitTrigger};
57+
58+
#[test]
59+
fn duplicate_cleanup_message_describes_tray_quit_trigger() {
60+
assert_eq!(
61+
duplicate_cleanup_message(ExitTrigger::TrayQuit),
62+
"tray quit while backend cleanup is already running"
63+
);
64+
}
65+
66+
#[test]
67+
fn stop_failure_prefix_describes_tray_quit_trigger() {
68+
assert_eq!(
69+
super::stop_failure_prefix(ExitTrigger::TrayQuit),
70+
"backend graceful stop on tray quit failed"
71+
);
72+
}
73+
}

src-tauri/src/lifecycle/events.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ fn decide_exit_requested_flow(has_exit_request_allowance: bool) -> ExitRequested
1616
}
1717
}
1818

19+
fn stop_backend_then_exit(app_handle: &AppHandle, trigger: cleanup::ExitTrigger) {
20+
let app_handle_cloned = app_handle.clone();
21+
tauri::async_runtime::spawn_blocking(move || {
22+
let state = app_handle_cloned.state::<BackendState>();
23+
cleanup::stop_backend_for_exit(&state, trigger, append_shutdown_log);
24+
state.allow_next_exit_request();
25+
app_handle_cloned.exit(0);
26+
});
27+
}
28+
1929
pub fn handle_exit_requested(app_handle: &AppHandle, api: &tauri::ExitRequestApi) {
2030
let state = app_handle.state::<BackendState>();
2131
match decide_exit_requested_flow(state.take_exit_request_allowance()) {
@@ -35,17 +45,19 @@ pub fn handle_exit_requested(app_handle: &AppHandle, api: &tauri::ExitRequestApi
3545
}
3646

3747
append_shutdown_log("exit requested, stopping backend asynchronously");
38-
let app_handle_cloned = app_handle.clone();
39-
tauri::async_runtime::spawn_blocking(move || {
40-
let state = app_handle_cloned.state::<BackendState>();
41-
cleanup::stop_backend_for_exit(
42-
&state,
43-
cleanup::ExitTrigger::ExitRequested,
44-
append_shutdown_log,
45-
);
46-
state.allow_next_exit_request();
47-
app_handle_cloned.exit(0);
48-
});
48+
stop_backend_then_exit(app_handle, cleanup::ExitTrigger::ExitRequested);
49+
}
50+
51+
pub fn handle_tray_quit(app_handle: &AppHandle) {
52+
let state = app_handle.state::<BackendState>();
53+
state.mark_quitting();
54+
if !cleanup::try_begin_exit_cleanup(&state, cleanup::ExitTrigger::TrayQuit, append_shutdown_log)
55+
{
56+
return;
57+
}
58+
59+
append_shutdown_log("tray quit requested, stopping backend asynchronously");
60+
stop_backend_then_exit(app_handle, cleanup::ExitTrigger::TrayQuit);
4961
}
5062

5163
pub fn handle_exit_event(app_handle: &AppHandle) {

src-tauri/src/tray/menu_handler.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use tauri::{AppHandle, Manager};
22

33
use crate::{
4-
append_desktop_log, append_restart_log, append_shutdown_log, restart_backend_flow,
4+
append_desktop_log, append_restart_log, lifecycle, restart_backend_flow,
55
tray::{actions, bridge_event},
66
ui_dispatch, window, BackendState, DEFAULT_SHELL_LOCALE, TRAY_RESTART_BACKEND_EVENT,
77
};
@@ -72,10 +72,7 @@ pub fn handle_tray_menu_event(app_handle: &AppHandle, menu_id: &str) {
7272
});
7373
}
7474
Some(actions::TrayMenuAction::Quit) => {
75-
let state = app_handle.state::<BackendState>();
76-
state.mark_quitting();
77-
append_shutdown_log("tray quit requested, exiting desktop process");
78-
app_handle.exit(0);
75+
lifecycle::events::handle_tray_quit(app_handle);
7976
}
8077
None => {}
8178
}

0 commit comments

Comments
 (0)