I'm tring to use hotwatch to monitor folders for backups.
If any changes happen, expect to emit an event to frontend to update pages.
Then i found that it's not able to access AppHandle or Window in regular struct.
I have tried using lifetime, but as Tauri: accessing-an-apphandle-in-commands mention, it seems there's no way to mantain a long enough life time.
pub struct MonitorHandler<'a> {
pub watcher: Hotwatch;
pub app_handler: Option<&'a AppHandle>
}
impl MonitorHandler<'_> {
pub fn initialize_app_handler(&mut self, handler: AppHandle) {
self.app_handler = Some(&handler);
}
pub fn append_target(path: &str) {
self.watcher.watch(path, |event| {
self.app_handler.emit_all("update");
})
}
}
// whitch shows error
89 | pub fn initialize_app_handler(&mut self, handler: AppHandle) {
| --------- has type `&mut MonitorHandler<'1>`
90 | self.app_handler = Some(&handler);
| ------------------------^^^^^^^^-
| | |
| | borrowed value does not live long enough
| assignment requires that `handler` is borrowed for `'1`
...
93 | }
| - `handler` dropped here while still borrowed
I have tried add app handle when setup, but it still not work, and with the same life time problem.
// main.rs
...
fn main() {
let monitor = Hotwatch::new().expect("failed to initialize monitor_handler");
let store = MonitorHandler(Mutex::new(MonitorHandler{ watcher: monitor }));
let context = tauri::generate_context!();
tauri::Builder::default()
.manage(store)
.setup(|app| {
store.0.lock().unwrap().initialize_app_handler(app.app_handle());
})
.invoke_handler(tauri::generate_handler![
initialize_app_handler
])
.run(context)
.expect("error while running tauri application");
}
// which will occurs
|
40 | let store = MonitorHandler(Mutex::new(MonitorHandler {
| ----- move occurs because `store` has type `MonitorHandler<'_>`, which does not implement the `Copy` trait
...
51 | .manage(store)
| ----- value moved here
52 | .setup(|app| {
| ^^^^^^^^^^ value used here after move
53 | store.0.lock().unwrap().initialize_app_handler(app.app_handle());
| ------- use occurs due to use in closure
I'm not familiar with rust and tauri, so is there some way to access the AppHandle or Window in my situation? or i have to do this in another way?
Here's my origin code
// handler.rs
// in this case, whether it's AppHandle or Window, the program will just stuck and not able to anything
pub struct MonitorHandler {
pub watcher: Hotwatch;
pub app_handler: Option<AppHandle>
}
impl MonitorHandler {
pub fn initialize_app_handler(&mut self, handler: AppHandle) {
self.app_handler = Some(handler.clone());
}
}
pub struct MonitorHandler(pub Mutex<MonitorHandler>);
// main.rs
use hotwatch::Hotwatch;
use tauri::{ Manager, AppHandle };
use crate::handler::MonitorHandler;
#[tauri::command]
pub fn initialize_app_handler(monitor: State<MonitorHandler>, app_handler: AppHandle) -> bool {
monitor.0.lock().unwrap().initialize_app_handler(app_handler);
true
}
fn main() {
let monitor = Hotwatch::new().expect("failed to initialize monitor_handler");
let store = MonitorHandler(Mutex::new(MonitorHandler{ watcher: monitor }));
let context = tauri::generate_context!();
tauri::Builder::default()
.manage(store)
.setup()
.invoke_handler(tauri::generate_handler![
initialize_app_handler
])
.run(context)
.expect("error while running tauri application");
}
The reason it get stuck is that the lock action cause a dead lock in the AppHandle since the stored sturct is assigned to the instance of the AppHandle.
How to solve the problem is simple, greet thanks for @FabianLars, here's the discussion Is there some way for backend to emit event actively?
To be brief, just initialize the struct and manage it in setup, like this
// handler.rs
pub struct MonitorHandler {
pub watcher: Hotwatch;
pub app_handler: AppHandle
}
impl MonitorHandler {
pub fn do_something(&self) {
// do something
self.app_handler.emit_all("events", some_payload { ... });
}
}
pub struct MonitorHandler(pub Mutex<MonitorHandler>);
// main.rs
use hotwatch::Hotwatch;
use tauri::{ Manager, AppHandle };
use crate::handler::MonitorHandler;
fn main() {
// let monitor = Hotwatch::new().expect("failed to initialize monitor_handler");
// let store = MonitorHandler(Mutex::new(MonitorHandler{ watcher: monitor }));
let context = tauri::generate_context!();
tauri::Builder::default()
.setup(move |app| {
let monitor = Hotwatch::new().expect("failed to initialize monitor_handler");
let struct_app_handle = app.handle().clone();
let store = MonitorHandler(Mutex::new(MonitorHandler{ watcher: monitor, app_handler: struct_app_handle }));
app.manage(store);
})
.invoke_handler(tauri::generate_handler![
initialize_app_handler
])
.run(context)
.expect("error while running tauri application");
}