monitor/src/services.rs

104 lines
3.7 KiB
Rust

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<Services>, tx: Arc<mpsc::Sender<u8>>) -> 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;
},
}
}
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;
},
}
}
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()) {
Ok(())
} else {
Err(CustomError::Fatal)
}
},
Err(_) => Err(CustomError::Fatal),
}
}