use std::sync::Arc; use tokio::time::{ Duration, Instant }; use tokio::sync::mpsc; use crate::structs::{Services, CustomError}; use crate::prcs::{is_active, is_frozen}; use log::{error, warn}; use std::net::{TcpStream, ToSocketAddrs}; pub async fn service_handler(name: &str, services: &Vec, tx: Arc>) -> Result<(), CustomError> { // println!("service daemon on {}", name); for serv in services { if check_service(&serv.hostname, &serv.port).await.is_err() { if !is_active(name).await || is_frozen(name).await { return Err(CustomError::Fatal); } error!("Service {}:{} is unreachable for process {}", &serv.hostname, &serv.port, &name); match serv.triggers.on_lost.as_str() { "stay" => { }, "stop" => { if looped_service_connecting(name, serv).await.is_err() { tx.send(5).await.unwrap(); tokio::time::sleep(Duration::from_millis(100)).await; return Err(CustomError::Fatal); } }, "hold" => { if is_frozen(name).await { return Err(CustomError::Fatal); } if looped_service_connecting(name, serv).await.is_err() { tx.send(6).await.unwrap(); tokio::time::sleep(Duration::from_millis(100)).await; return Err(CustomError::Fatal); } }, _ => { tx.send(101).await.unwrap(); return Err(CustomError::Fatal); }, } } } tokio::time::sleep(Duration::from_millis(100)).await; tokio::task::yield_now().await; Ok(()) } async fn looped_service_connecting( name: &str, serv: &Services ) -> Result<(), CustomError> { if serv.triggers.wait == 0 { loop { tokio::time::sleep(Duration::from_secs(serv.triggers.delay.into())).await; warn!("Attempting to connect from {} process to {}:{}",&name, &serv.hostname, &serv.port ); match check_service(&serv.hostname, &serv.port).await { Ok(_) => { log::info!("Successfully connected to {} from {} process!", &serv.hostname, &name); break; }, Err(_) => { continue; }, } } return Ok(()); } else { let start = Instant::now(); while start.elapsed().as_secs() < serv.triggers.wait.into() { tokio::time::sleep(Duration::from_secs(serv.triggers.delay.into())).await; warn!("Attempting to connect from {} process to {}:{}",&name, &serv.hostname, &serv.port ); match check_service(&serv.hostname, &serv.port).await { Ok(_) => { log::info!("Successfully connected to {} from {} process!", &serv.hostname, &name); return Ok(()); }, Err(_) => { continue; }, } } return Err(CustomError::Fatal); } } // ! have to be rewritten // todo: rewrite use async fn check_service(hostname: &str, port: &u32) -> Result<(), CustomError> { let addr = format!("{}:{}", hostname, port); match addr.to_socket_addrs() { Ok(mut addrs) => { if let Some(_) = addrs.find(|a| TcpStream::connect_timeout(a, std::time::Duration::new(1, 0)).is_ok()) { return Ok(()); } else { return Err(CustomError::Fatal); } }, Err(_) => return Err(CustomError::Fatal), } }