Skip to content

Commit 09824ef

Browse files
authored
add root supervisor in desktop app (#1881)
1 parent ff6fc8a commit 09824ef

File tree

8 files changed

+144
-14
lines changed

8 files changed

+144
-14
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/desktop/src-tauri/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ serde_json = { workspace = true }
6464
strum = { workspace = true, features = ["derive"] }
6565
tracing = { workspace = true }
6666

67+
ractor = { workspace = true }
68+
ractor-supervisor = { workspace = true }
69+
6770
aspasia = "0.2.1"
6871
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
6972

apps/desktop/src-tauri/src/lib.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod commands;
22
mod ext;
33
mod store;
44
mod subtitle;
5+
mod supervisor;
56

67
use ext::*;
78
use store::*;
@@ -13,6 +14,12 @@ use tauri_plugin_windows::{AppWindow, WindowsPluginExt};
1314
pub async fn main() {
1415
tauri::async_runtime::set(tokio::runtime::Handle::current());
1516

17+
let (root_supervisor, _root_supervisor_handle) = match supervisor::spawn_root_supervisor().await
18+
{
19+
Some((supervisor, handle)) => (Some(supervisor), Some(handle)),
20+
None => (None, None),
21+
};
22+
1623
let sentry_client = {
1724
let dsn = option_env!("SENTRY_DSN");
1825

@@ -57,9 +64,7 @@ pub async fn main() {
5764
.plugin(tauri_plugin_db2::init())
5865
.plugin(tauri_plugin_tracing::init())
5966
.plugin(tauri_plugin_hooks::init())
60-
.plugin(tauri_plugin_listener::init())
6167
.plugin(tauri_plugin_shell::init())
62-
.plugin(tauri_plugin_local_stt::init())
6368
.plugin(tauri_plugin_permissions::init())
6469
.plugin(tauri_plugin_updater::Builder::new().build())
6570
.plugin(tauri_plugin_deep_link::init())
@@ -77,6 +82,16 @@ pub async fn main() {
7782
.plugin(tauri_plugin_store::Builder::default().build())
7883
.plugin(tauri_plugin_store2::init())
7984
.plugin(tauri_plugin_windows::init())
85+
.plugin(tauri_plugin_listener::init(
86+
tauri_plugin_listener::InitOptions {
87+
parent_supervisor: root_supervisor.as_ref().map(|s| s.get_cell()),
88+
},
89+
))
90+
.plugin(tauri_plugin_local_stt::init(
91+
tauri_plugin_local_stt::InitOptions {
92+
parent_supervisor: root_supervisor.as_ref().map(|s| s.get_cell()),
93+
},
94+
))
8095
.plugin(tauri_plugin_autostart::init(
8196
tauri_plugin_autostart::MacosLauncher::LaunchAgent,
8297
Some(vec!["--background"]),
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use ractor::concurrency::Duration;
2+
use ractor::ActorRef;
3+
use ractor_supervisor::dynamic::{
4+
DynamicSupervisor, DynamicSupervisorMsg, DynamicSupervisorOptions,
5+
};
6+
7+
pub type SupervisorRef = ActorRef<DynamicSupervisorMsg>;
8+
pub type SupervisorHandle = tokio::task::JoinHandle<()>;
9+
10+
const ROOT_SUPERVISOR_NAME: &str = "root_supervisor";
11+
12+
pub async fn spawn_root_supervisor() -> Option<(SupervisorRef, SupervisorHandle)> {
13+
let options = DynamicSupervisorOptions {
14+
max_children: Some(10),
15+
max_restarts: 50,
16+
max_window: Duration::from_secs(60),
17+
reset_after: Some(Duration::from_secs(30)),
18+
};
19+
20+
match DynamicSupervisor::spawn(ROOT_SUPERVISOR_NAME.to_string(), options).await {
21+
Ok((supervisor_ref, handle)) => {
22+
tracing::info!("root_supervisor_spawned");
23+
Some((supervisor_ref, handle))
24+
}
25+
Err(e) => {
26+
tracing::error!("failed_to_spawn_root_supervisor: {:?}", e);
27+
None
28+
}
29+
}
30+
}

plugins/listener/src/lib.rs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use ractor::ActorCell;
2+
use ractor_supervisor::dynamic::DynamicSupervisorMsg;
13
use tauri::Manager;
24
use tokio::sync::Mutex;
35

@@ -7,17 +9,26 @@ mod error;
79
mod events;
810
mod ext;
911
pub mod fsm;
12+
mod supervisor;
1013

1114
pub use error::*;
1215
pub use events::*;
1316
pub use ext::*;
17+
pub use supervisor::{SupervisorHandle, SupervisorRef, SUPERVISOR_NAME};
1418

1519
const PLUGIN_NAME: &str = "listener";
1620

17-
pub type SharedState = Mutex<State>;
21+
pub type SharedState = std::sync::Arc<Mutex<State>>;
1822

1923
pub struct State {
20-
app: tauri::AppHandle,
24+
pub app: tauri::AppHandle,
25+
pub listener_supervisor: Option<ractor::ActorRef<DynamicSupervisorMsg>>,
26+
pub supervisor_handle: Option<SupervisorHandle>,
27+
}
28+
29+
#[derive(Default)]
30+
pub struct InitOptions {
31+
pub parent_supervisor: Option<ActorCell>,
2132
}
2233

2334
impl State {
@@ -48,7 +59,7 @@ fn make_specta_builder<R: tauri::Runtime>() -> tauri_specta::Builder<R> {
4859
.error_handling(tauri_specta::ErrorHandlingMode::Result)
4960
}
5061

51-
pub fn init() -> tauri::plugin::TauriPlugin<tauri::Wry> {
62+
pub fn init(options: InitOptions) -> tauri::plugin::TauriPlugin<tauri::Wry> {
5263
let specta_builder = make_specta_builder();
5364

5465
tauri::plugin::Builder::new(PLUGIN_NAME)
@@ -58,9 +69,29 @@ pub fn init() -> tauri::plugin::TauriPlugin<tauri::Wry> {
5869

5970
let app_handle = app.app_handle().clone();
6071

61-
let state: SharedState = Mutex::new(State { app: app_handle });
72+
let state: SharedState = std::sync::Arc::new(Mutex::new(State {
73+
app: app_handle,
74+
listener_supervisor: None,
75+
supervisor_handle: None,
76+
}));
77+
78+
app.manage(state.clone());
79+
80+
let parent = options.parent_supervisor.clone();
81+
tauri::async_runtime::spawn(async move {
82+
match supervisor::spawn_listener_supervisor(parent).await {
83+
Ok((supervisor, handle)) => {
84+
let mut guard = state.lock().await;
85+
guard.listener_supervisor = Some(supervisor);
86+
guard.supervisor_handle = Some(handle);
87+
tracing::info!("listener_supervisor_spawned");
88+
}
89+
Err(e) => {
90+
tracing::error!("failed_to_spawn_listener_supervisor: {:?}", e);
91+
}
92+
}
93+
});
6294

63-
app.manage(state);
6495
Ok(())
6596
})
6697
.build()

plugins/listener/src/supervisor.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use ractor::{ActorCell, ActorProcessingErr, ActorRef};
2+
use ractor_supervisor::dynamic::{
3+
DynamicSupervisor, DynamicSupervisorMsg, DynamicSupervisorOptions,
4+
};
5+
6+
pub type SupervisorRef = ActorRef<DynamicSupervisorMsg>;
7+
pub type SupervisorHandle = tokio::task::JoinHandle<()>;
8+
9+
pub const SUPERVISOR_NAME: &str = "listener_supervisor";
10+
11+
fn make_supervisor_options() -> DynamicSupervisorOptions {
12+
DynamicSupervisorOptions {
13+
max_children: Some(10),
14+
max_restarts: 50,
15+
max_window: ractor::concurrency::Duration::from_secs(60),
16+
reset_after: Some(ractor::concurrency::Duration::from_secs(30)),
17+
}
18+
}
19+
20+
pub async fn spawn_listener_supervisor(
21+
parent: Option<ActorCell>,
22+
) -> Result<(SupervisorRef, SupervisorHandle), ActorProcessingErr> {
23+
let options = make_supervisor_options();
24+
25+
let (supervisor_ref, handle) =
26+
DynamicSupervisor::spawn(SUPERVISOR_NAME.to_string(), options).await?;
27+
28+
if let Some(parent_cell) = parent {
29+
supervisor_ref.get_cell().link(parent_cell);
30+
}
31+
32+
Ok((supervisor_ref, handle))
33+
}

plugins/local-stt/src/lib.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use ractor::ActorRef;
1+
use ractor::{ActorCell, ActorRef};
22
use ractor_supervisor::dynamic::DynamicSupervisorMsg;
33
use std::collections::HashMap;
44
use tauri::{Manager, Wry};
@@ -14,6 +14,7 @@ mod types;
1414
pub use error::*;
1515
pub use ext::*;
1616
pub use model::*;
17+
pub use server::supervisor::{SupervisorRef, SUPERVISOR_NAME};
1718
pub use server::*;
1819
pub use types::*;
1920

@@ -27,6 +28,11 @@ pub struct State {
2728
pub supervisor_handle: Option<SupervisorHandle>,
2829
}
2930

31+
#[derive(Default)]
32+
pub struct InitOptions {
33+
pub parent_supervisor: Option<ActorCell>,
34+
}
35+
3036
const PLUGIN_NAME: &str = "local-stt";
3137

3238
fn make_specta_builder<R: tauri::Runtime>() -> tauri_specta::Builder<R> {
@@ -48,7 +54,7 @@ fn make_specta_builder<R: tauri::Runtime>() -> tauri_specta::Builder<R> {
4854
.error_handling(tauri_specta::ErrorHandlingMode::Result)
4955
}
5056

51-
pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
57+
pub fn init<R: tauri::Runtime>(options: InitOptions) -> tauri::plugin::TauriPlugin<R> {
5258
let specta_builder = make_specta_builder();
5359

5460
tauri::plugin::Builder::new(PLUGIN_NAME)
@@ -67,8 +73,9 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
6773

6874
app.manage(state.clone());
6975

76+
let parent = options.parent_supervisor.clone();
7077
tauri::async_runtime::spawn(async move {
71-
match server::supervisor::spawn_stt_supervisor().await {
78+
match server::supervisor::spawn_stt_supervisor(parent).await {
7279
Ok((supervisor, handle)) => {
7380
let mut guard = state.lock().await;
7481
guard.stt_supervisor = Some(supervisor);

plugins/local-stt/src/server/supervisor.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,27 @@ pub const INTERNAL_STT_ACTOR_NAME: &str = "internal_stt";
1616
pub const EXTERNAL_STT_ACTOR_NAME: &str = "external_stt";
1717
pub const SUPERVISOR_NAME: &str = "stt_supervisor";
1818

19-
pub async fn spawn_stt_supervisor(
20-
) -> Result<(ActorRef<DynamicSupervisorMsg>, crate::SupervisorHandle), ActorProcessingErr> {
21-
let options = DynamicSupervisorOptions {
19+
fn make_supervisor_options() -> DynamicSupervisorOptions {
20+
DynamicSupervisorOptions {
2221
max_children: Some(1),
2322
max_restarts: 100,
2423
max_window: Duration::from_secs(60 * 3),
2524
reset_after: Some(Duration::from_secs(30)),
26-
};
25+
}
26+
}
27+
28+
pub async fn spawn_stt_supervisor(
29+
parent: Option<ActorCell>,
30+
) -> Result<(ActorRef<DynamicSupervisorMsg>, crate::SupervisorHandle), ActorProcessingErr> {
31+
let options = make_supervisor_options();
2732

2833
let (supervisor_ref, handle) =
2934
DynamicSupervisor::spawn(SUPERVISOR_NAME.to_string(), options).await?;
3035

36+
if let Some(parent_cell) = parent {
37+
supervisor_ref.get_cell().link(parent_cell);
38+
}
39+
3140
Ok((supervisor_ref, handle))
3241
}
3342

0 commit comments

Comments
 (0)