monitor/noxis-rs/src/options/signals.rs

128 lines
3.5 KiB
Rust

use std::sync::Arc;
use tokio::io;
use tokio::sync::mpsc;
use tokio::{
select,
signal::unix::{signal, Signal, SignalKind},
};
type SendersVec = Arc<Vec<Arc<mpsc::Sender<u8>>>>;
/// # Fn set_valid_destructor
/// ## for initializing process of unstoppable grubbing metrics.
///
/// *input* : `Result<()>`
///
/// *output* : `Err` if it cant create signals listeners | `Ok` on returning Monitor
///
/// *initiator* : main thread
///
/// *managing* : `Arc<Vec<Arc<mpsc::Sender<u8>>>>`
///
/// *depends on* : Sig, Signals
///
pub async fn set_valid_destructor(senders: SendersVec) -> anyhow::Result<()> {
let (mut int, mut term, mut stop) = (
Sig::new(Signals::Sigint, senders.clone()),
Sig::new(Signals::Sigterm, senders.clone()),
Sig::new(Signals::Sigstop, senders.clone()),
);
select! {
_ = int.post_processing() => {log::info!("Initializing interruption...")},
_ = term.post_processing() => {log::info!("Initializing termination...")},
_ = stop.post_processing() => {log::info!("Initializing freezing...")},
}
Ok(())
}
/// # Enum Signals
/// ## for instancing each managed system signals (such as SIGINT)
///
/// > (element needed in Sig constructor's signature)
///
/// *depends on* : -
enum Signals {
Sigint,
Sigterm,
Sigstop,
}
/// # Struct Signals
/// ## for instancing each managed system signals (such as SIGINT)
///
/// > (needed to construct system signals listener)
///
/// *depends on* : Signals
struct Sig {
signal: Signal,
sig_type: Signals,
senders: SendersVec,
}
/// ## default Sig's constructor
impl Sig {
fn new(signal_type: Signals, sends: SendersVec) -> Self {
Sig {
signal: signal_type.get_signal().unwrap(),
sig_type: signal_type,
senders: sends,
}
}
}
/// ## trait Display realization for returning String-name of signal
///
/// > (needed in logs)
impl std::fmt::Display for Signals {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Signals::Sigint => write!(f, "SIGINT"),
Signals::Sigterm => write!(f, "SIGTERM"),
Signals::Sigstop => write!(f, "SIGSTOP"),
}
}
}
/// ## associated func to init signals listener
impl Signals {
fn get_signal(&self) -> io::Result<Signal> {
match self {
Signals::Sigint => signal(SignalKind::interrupt()),
Signals::Sigterm => signal(SignalKind::terminate()),
Signals::Sigstop => signal(SignalKind::quit()),
}
}
}
/// # Trait SigPostProcessing
/// ## to handle post-processing jobs after getting system signal
///
/// ## > (needed in signals post-processing)
///
trait SigPostProcessing {
async fn post_processing(&mut self) -> io::Result<()>;
}
/// # Trait SigPostProcessing realization for Sig struct
/// ## to deinitialize Monitor correctly after getting signal
///
/// ## > (needed in signals post-processing)
///
impl SigPostProcessing for Sig {
async fn post_processing(&mut self) -> io::Result<()> {
// manipulations ...
if self.signal.recv().await.is_some() {
log::info!("Got {} signal", self.sig_type);
for prc in self.senders.clone().iter() {
let _ = prc.send(111).await;
}
}
Ok(())
}
}
#[cfg(test)]
mod signals_unittest {
use super::*;
#[tokio::test]
async fn get_signal_check() {
assert!(Signals::Sigint.get_signal().is_ok())
}
}