Skip to content

Commit aeca03c

Browse files
authored
Initial set of changes to get and shut down ETVR backend from within the new frontend tool (#30)
* Initial set pf changes to get and shut down ETVR backend from within the new frontend tool * Clean up the code. TODO figure out how to kill a zombie proces * Update tauri version * You can't have a zombie process if you shoot it with a gun * Cleanup after CR by FelinDev [FelinDev](https://github.com/felindev) * Move the ETVR handling code into a plugin, update readme, clean up a little
1 parent 167fe3e commit aeca03c

14 files changed

Lines changed: 235 additions & 41 deletions

File tree

README.md

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,33 @@ This project uses `pnpm` by default, and utilizes `pnpm workspaces`. If you do n
2222
You _can_ use `yarn` or `npm`, however, _you_ will need to modify the project to remove the `pnpm` specific commands and workspace.
2323

2424
## Setup
25+
### Step 1 - setup node environment
2526

26-
This project uses custom `Tauri Plugins` to communicate with the hardware. These plugins are located in the [`src-tauri/src/lib`](/src-tauri/src/lib) folder.
27+
```bash
28+
pnpm run setup
29+
```
30+
### Step 2 - setting up the backend binary
2731

28-
> [!WARNING]\
29-
> You **must** run the following command to install the project deps and build the plugins before running the app:
32+
To actually compile the project, you'll also need a binary of the ETVR backend from [here]().
33+
34+
Clone the project, follow its readme to set it up and build the binary.
35+
Once done, copy the result into [backend_bin](/src-tauri/backend_bin) and rename it to `ETVR-<target-triple>`
36+
37+
The target triple can be obtained by running
3038

3139
```bash
32-
pnpm run setup
40+
rustc -Vv
41+
```
42+
43+
The info you're looking for will be stored under `host:`, for example `host: x86_64-pc-windows-msvc`
44+
So the copied binary should be named like `ETVR-x86_64-pc-windows-msvc`
45+
46+
### Step 3
47+
48+
Run the project
49+
50+
```bash
51+
pnpm tauri dev
3352
```
3453

3554
## Available Scripts
@@ -56,6 +75,11 @@ Runs `eslint` on all of the included files.
5675

5776
Uses `Prettier` and the above `pnpm lint` command to lint and then format all included file types.
5877

78+
## Development
79+
80+
This project follows the architecture Tauri laid down - `Tauri Plugins` and commands, to communicate with the hardware.
81+
These plugins are located in the [`src-tauri/src/lib`](/src-tauri/src/lib) folder.
82+
5983
## Deployment
6084

6185
To build the app, run the following:

src-tauri/Cargo.lock

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

src-tauri/Cargo.toml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ rust-version = "1.69"
1212
[dependencies]
1313
serde_json = "1.0"
1414
zip-extract = "0.1.3"
15-
command-group = "2.1.0"
1615

1716
[dependencies.reqwest]
1817
workspace = true
@@ -41,6 +40,9 @@ path = "src/lib/api"
4140
[dependencies.tauri-plugin-esp]
4241
path = "src/lib/esp"
4342

43+
[dependencies.tauri-plugin-etvr-backend]
44+
path = "src/lib/etvr_backend_module"
45+
4446
[dependencies.tauri-plugin-window-state]
4547
git = "https://github.com/tauri-apps/plugins-workspace"
4648
branch = "v1"
@@ -66,7 +68,7 @@ version = "1"
6668
features = ["full"]
6769

6870
[workspace]
69-
members = ["src/lib/api", "src/lib/util", "src/lib/esp"]
71+
members = ["src/lib/api", "src/lib/util", "src/lib/esp", "src/lib/etvr_backend_module"]
7072

7173
[workspace.dependencies]
7274
dialoguer = "0.11.0"
@@ -90,7 +92,7 @@ features = ["javascript", "typescript"]
9092

9193
[workspace.dependencies.tauri]
9294
version = "1.6.1"
93-
features = ["process-exit", "protocol-asset", "fs-all", "dialog-all", "http-all", "icon-ico", "notification-all", "os-all", "path-all", "process-relaunch", "shell-open", "system-tray", "window-center", "window-close", "window-create", "window-hide", "window-maximize", "window-minimize", "window-request-user-attention", "window-set-decorations", "window-set-focus", "window-set-fullscreen", "window-set-position", "window-set-resizable", "window-set-size", "window-set-title", "window-show", "window-start-dragging", "window-unmaximize", "window-unminimize"]
95+
features = ["process-exit", "protocol-asset", "fs-all", "dialog-all", "http-all", "icon-ico", "notification-all", "os-all", "path-all", "process-relaunch", "shell-all", "system-tray", "window-center", "window-close", "window-create", "window-hide", "window-maximize", "window-minimize", "window-request-user-attention", "window-set-decorations", "window-set-focus", "window-set-fullscreen", "window-set-position", "window-set-resizable", "window-set-size", "window-set-title", "window-show", "window-start-dragging", "window-unmaximize", "window-unminimize"]
9496

9597
[features]
9698
default = ["custom-protocol"]
@@ -101,9 +103,6 @@ updater = ["tauri/updater"]
101103
version = "1.5.1"
102104
features = []
103105

104-
[profile.dev]
105-
debug = 0
106-
107106
[profile.release]
108107
panic = "abort"
109108
codegen-units = 1

src-tauri/backend_bin/.gitkeep

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "tauri-plugin-etvr-backend"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
tauri = { workspace = true }
10+
log = { workspace = true }
11+
command-group = "2.1.0"
12+
reqwest = "0.11.27"
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use crate::constants::ETVR_BACKEND_PORT;
2+
use command_group::CommandGroup;
3+
use std::process::Command;
4+
use std::sync::mpsc::Receiver;
5+
use std::thread;
6+
use tauri::api::process::Command as TauriCommand;
7+
use tauri::{AppHandle, Manager, Runtime};
8+
9+
pub fn initialize_etvr_backend<R: Runtime>(app: AppHandle<R>, receiver: Receiver<()>) {
10+
let sidecar_handle_result = TauriCommand::new_sidecar("ETVR");
11+
match sidecar_handle_result {
12+
Ok(handle) => {
13+
spawn_backend(handle, receiver);
14+
}
15+
Err(spawn_error) => {
16+
if let Some(window) = app.get_window("main") {
17+
if let Err(error) = window.emit("backend-init-fail", spawn_error.to_string()) {
18+
log::error!("failed to emit error event: {}", error);
19+
}
20+
}
21+
log::error!("failed to start ETVR backend");
22+
}
23+
}
24+
}
25+
26+
fn spawn_backend(sidecar_handle: TauriCommand, receiver: Receiver<()>) {
27+
let mut group = Command::from(sidecar_handle)
28+
.args(["--port", ETVR_BACKEND_PORT])
29+
.group_spawn()
30+
.expect("Failed to spawn ETVR backend");
31+
32+
log::info!("ETVR backend spawned");
33+
34+
// TODO this is fine for a happy-path scenario, we need a way to
35+
// we'll also need to handle situations where the user quits forcefully
36+
// or the app gets somehow killed
37+
// something like a daemon process holding a socket to ETVR and a PID of the backend
38+
// that once the socket gets closed - kills the backend and terminates, could work
39+
40+
thread::spawn(move || loop {
41+
let signal = receiver.recv();
42+
match signal {
43+
Ok(_) => {
44+
log::info!("ETVR backend terminated.");
45+
group.kill().expect("failed to kill ETVR backend");
46+
}
47+
Err(e) => {
48+
log::error!("How is this possible? This should not error out: {:?}", e);
49+
}
50+
}
51+
});
52+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use std::sync::mpsc::SendError;
2+
use tauri::{AppHandle, Manager, Runtime};
3+
use crate::constants::{ETVR_BACKEND_ADDRESS, ETVR_BACKEND_PORT};
4+
use crate::state::AppState;
5+
6+
#[tauri::command(async)]
7+
pub async fn shutdown_etvr_backend<R: Runtime>(app_handle: AppHandle<R>) -> Result<(), String> {
8+
// requesting shutdown will immediately kill the backend so we can safely ignore the result here
9+
// but for some reason the process will still be somewhat alive, a zombie
10+
// we gotta kill it.
11+
12+
// TODO change the port, random it get something bigger, 8000 is not good enough
13+
let _ = reqwest::get(format!(
14+
"http://{}:{}/etvr/shutdown",
15+
ETVR_BACKEND_ADDRESS, ETVR_BACKEND_PORT
16+
))
17+
.await;
18+
19+
let app_state = app_handle.state::<AppState>();
20+
21+
log::info!("ETVR Backend shutdown successfully");
22+
match app_state.inner().sidecar_sender.send(()) {
23+
Ok(_) => {
24+
log::info!("ETVR Backend process killed successfully");
25+
}
26+
Err(error) => {
27+
log::error!("Failed to kill ETVR Backend process with error: {}", error);
28+
}
29+
}
30+
31+
app_handle.exit(0);
32+
Ok(())
33+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pub const ETVR_BACKEND_ADDRESS: &str = "127.0.0.1";
2+
3+
// by default the backend server will be running on port 8000
4+
// which is super common in dev, so we gotta adjust.
5+
// TODO move this to a configuration file
6+
pub const ETVR_BACKEND_PORT: &str = "8855";

0 commit comments

Comments
 (0)