Skip to main content

impulse_server_kit/setup/
port_achiever.rs

1//! Port achiever module.
2
3use impulse_utils::prelude::*;
4
5pub(crate) async fn port_file_watcher<P: AsRef<std::path::Path>>(path: P) -> MResult<u16> {
6  use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
7
8  let (tx, mut rx) = tokio::sync::mpsc::channel(1);
9  let mut watcher = RecommendedWatcher::new(move |res| tx.blocking_send(res).unwrap(), Config::default())
10    .map_err(|e| ServerError::from_private(e).with_500())?;
11  watcher
12    .watch(path.as_ref(), RecursiveMode::NonRecursive)
13    .map_err(|e| ServerError::from_private(e).with_500())?;
14
15  while let Some(res) = rx.recv().await {
16    match res {
17      Ok(event) if event.kind.is_modify() || event.kind.is_create() => {
18        if let Ok(port) = std::fs::read_to_string(path.as_ref())
19          && let Ok(port) = port.trim().parse::<u16>()
20        {
21          watcher
22            .unwatch(path.as_ref())
23            .map_err(|e| ServerError::from_private(e).with_500())?;
24          return Ok(port);
25        }
26      }
27      Err(e) => {
28        tracing::error!("Watch error: {:?}", e);
29        ServerError::from_private(e).with_500().bail()?;
30      }
31      _ => {}
32    }
33  }
34
35  ServerError::from_private_str("Event channel is broken!")
36    .with_500()
37    .bail()
38}