impulse-server-kit 1.1.9

Highly configurable backend framework based on `salvo`
Documentation
//! Port achiever module.

use impulse_utils::prelude::*;

pub(crate) async fn port_file_watcher<P: AsRef<std::path::Path>>(path: P) -> MResult<u16> {
  use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};

  let (tx, mut rx) = tokio::sync::mpsc::channel(1);
  let mut watcher = RecommendedWatcher::new(move |res| tx.blocking_send(res).unwrap(), Config::default())
    .map_err(|e| ServerError::from_private(e).with_500())?;
  watcher
    .watch(path.as_ref(), RecursiveMode::NonRecursive)
    .map_err(|e| ServerError::from_private(e).with_500())?;

  while let Some(res) = rx.recv().await {
    match res {
      Ok(event) if event.kind.is_modify() || event.kind.is_create() => {
        if let Ok(port) = std::fs::read_to_string(path.as_ref())
          && let Ok(port) = port.trim().parse::<u16>()
        {
          watcher
            .unwatch(path.as_ref())
            .map_err(|e| ServerError::from_private(e).with_500())?;
          return Ok(port);
        }
      }
      Err(e) => {
        tracing::error!("Watch error: {:?}", e);
        ServerError::from_private(e).with_500().bail()?;
      }
      _ => {}
    }
  }

  ServerError::from_private_str("Event channel is broken!")
    .with_500()
    .bail()
}