logs + restarting prc fix

pull/9/head
prplV 2024-07-17 13:47:11 +03:00
parent 8bcff113c9
commit 0d14ab2509
4 changed files with 361 additions and 28 deletions

298
Cargo.lock generated
View File

@ -17,6 +17,79 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "anstyle-parse"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
]
[[package]]
name = "autocfg"
version = "1.3.0"
@ -50,6 +123,12 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytes"
version = "1.6.0"
@ -68,6 +147,55 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.52.5",
]
[[package]]
name = "colorchoice"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "env_filter"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
dependencies = [
"log",
"regex",
]
[[package]]
name = "env_logger"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"humantime",
"log",
]
[[package]]
name = "futures-core"
version = "0.3.30"
@ -86,6 +214,35 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "inotify"
version = "0.10.2"
@ -108,12 +265,27 @@ dependencies = [
"libc",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.155"
@ -130,6 +302,12 @@ dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
version = "2.7.4"
@ -156,6 +334,15 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
@ -175,6 +362,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "parking_lot"
version = "0.12.3"
@ -232,10 +425,42 @@ dependencies = [
]
[[package]]
name = "runner-rs"
version = "0.4.0"
name = "regex"
version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "runner-rs"
version = "0.4.2"
dependencies = [
"chrono",
"env_logger",
"inotify",
"log",
"serde",
"serde_json",
"tokio",
@ -362,12 +587,81 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.5",
]
[[package]]
name = "windows-sys"
version = "0.48.0"

View File

@ -1,10 +1,13 @@
[package]
name = "runner-rs"
version = "0.4.0"
version = "0.4.2"
edition = "2021"
[dependencies]
chrono = "0.4.38"
env_logger = "0.11.3"
inotify = "0.10.2"
log = "0.4.22"
serde = { version = "1.0.203", features = ["derive"] }
serde_json = "1.0.118"
tokio = { version = "1.38.0", features = ["full", "time"] }

View File

@ -1,4 +1,5 @@
{
"id" : 1,
"processes" : [{
"name" : "web-server",
"path" : "/home/vladislav/web/web-server",
@ -17,7 +18,7 @@
"src" : "/home/vladislav/web/",
"triggers" : {
"onDelete" : "stop",
"onChange" : "hold"
"onChange" : "restart"
}
}
],

View File

@ -1,15 +1,25 @@
// json parsing
use serde::{ Deserialize, Serialize };
use serde_json;
// async multi-threaded execution
use tokio::time::{ Duration, Instant };
use tokio::sync::mpsc;
use tokio::join;
// fatal errors handler
use core::panic;
// utils
use std::fmt::Debug;
use std::fs;
use std::path::Path;
use std::process::{ Command, Output };
use std::sync::{ Arc, Mutex };
use tokio::time::{ Duration, Instant };
use tokio::sync::mpsc;
use std::sync::Arc;
// file change handler
use inotify::{ Inotify, WatchMask };
// logging
use std::io::Write;
use chrono::Local;
use env_logger::Builder;
use log::{error, max_level, warn, LevelFilter};
/// # an Error enum (nextly will be deleted and replaced)
enum CustomError {
@ -20,6 +30,8 @@ enum CustomError {
/// > (needed in serialization and deserialization)
#[derive(Debug, Serialize, Deserialize, Clone)]
struct Processes {
#[serde(rename="id")]
runner_id: usize,
#[serde(default)]
processes : Vec<TrackingProcess>,
}
@ -83,21 +95,43 @@ struct FIleTriggers {
#[tokio::main(flavor = "multi_thread")]
async fn main() {
Builder::new()
.format(|buf, record|{
writeln!(buf,
"{} [{}] - {}",
Local::now().format("%d-%m-%Y %H:%M:%S"),
record.level(),
record.args(),
)
})
.filter(None, LevelFilter::Info)
.init();
let processes = load_processes("settings.json");
// let mut error_counter = 0;
if processes.processes.len() == 0 {
eprintln!("Error: Processes list is null, runner-rs initialization is stopped");
error!("Processes list is null, runner-rs initialization is stopped");
// eprintln!("Error: Processes list is null, runner-rs initialization is stopped");
return;
}
let mut handler: Vec<tokio::task::JoinHandle<()>> = vec![];
for proc in processes.processes.iter() {
println!("Process '{}' on stage:\n{}\nDepends on {} file(s), {} service(s)\n",
log::info!("Process '{}' on stage: {}. Depends on {} file(s), {} service(s)",
proc.name,
proc.path,
proc.dependencies.files.len(),
proc.dependencies.services.len());
proc.dependencies.services.len()
);
// println!("Process '{}' on stage:\n{}\nDepends on {} file(s), {} service(s)\n",
// proc.name,
// proc.path,
// proc.dependencies.files.len(),
// proc.dependencies.services.len()
// );
// creating msg channel
// can or should be executed in new thread
@ -154,7 +188,7 @@ async fn run_daemons(
// 1 - File-dependency handling error -> terminating (after waiting)
1 => {
if is_active(&proc.name).await {
println!("Dependency handling error: Terminating {} process ..." , &proc.name);
error!("Dependency handling error: Terminating {} process ..." , &proc.name);
terminate_process(&proc.name).await;
tokio::time::sleep(Duration::from_millis(100)).await;
}
@ -163,23 +197,23 @@ async fn run_daemons(
// 2 - File-dependency handling error -> holding (after waiting)
2 => {
if !is_frozen(&proc.name).await {
println!("Dependency handling error: Freezing {} process ..." , &proc.name);
error!("Dependency handling error: Freezing {} process ..." , &proc.name);
freeze_process(&proc.name).await;
tokio::time::sleep(Duration::from_millis(100)).await;
}
},
// 3 - Running process error
3 => {
println!("Error due to starting {} process", &proc.name);
error!("Error due to starting {} process", &proc.name);
},
// 4 - Timeout of waiting service-dependency -> staying (after waiting)
4 => {
println!("Timeout of waiting service-dependency: Ignoring on {} process ..." , &proc.name);
warn!("Timeout of waiting service-dependency: Ignoring on {} process ..." , &proc.name);
},
// 5 - Timeout of waiting service-dependency -> terminating (after waiting)
5 => {
if is_active(&proc.name).await {
println!("Timeout of waiting service-dependency: Terminating {} process ..." , &proc.name);
error!("Timeout of waiting service-dependency: Terminating {} process ..." , &proc.name);
terminate_process(&proc.name).await;
tokio::time::sleep(Duration::from_millis(100)).await;
}
@ -188,45 +222,45 @@ async fn run_daemons(
// 6 - Timeout of waiting service-dependency -> holding (after waiting)
6 => {
if !is_frozen(&proc.name).await {
println!("Timeout of waiting service-dependency: Freezing {} process ..." , &proc.name);
error!("Timeout of waiting service-dependency: Freezing {} process ..." , &proc.name);
freeze_process(&proc.name).await;
tokio::time::sleep(Duration::from_millis(100)).await;
}
},
// // 7 - File-dependency change -> terminating (after check)
7 => {
println!("File-dependency warning (file changed). Terminating {} process...", &proc.name);
error!("File-dependency warning (file changed). Terminating {} process...", &proc.name);
terminate_process(&proc.name).await;
tokio::time::sleep(Duration::from_millis(100)).await;
},
// // 8 - File-dependency change -> restarting (after check)
8 => {
println!("File-dependency warning (file changed). Restarting {} process...", &proc.name);
warn!("File-dependency warning (file changed). Restarting {} process...", &proc.name);
let _ = restart_process(&proc.name, &proc.path).await;
tokio::time::sleep(Duration::from_millis(100)).await;
},
// // 9 - File-dependency change -> staying (after check)
9 => {
println!("File-dependency warning (file changed). Ignoring on {} process...", &proc.name);
warn!("File-dependency warning (file changed). Ignoring on {} process...", &proc.name);
},
// 10 - Process unfreaze call via file handler
10 => {
if is_frozen(&proc.name).await {
println!("Unfreezing process {} call...", &proc.name);
warn!("Unfreezing process {} call...", &proc.name);
unfreeze_process(&proc.name).await;
}
},
// 11 - Process unfreaze call via service handler
11 => {
if is_frozen(&proc.name).await {
println!("Unfreezing process {} call...", &proc.name);
warn!("Unfreezing process {} call...", &proc.name);
unfreeze_process(&proc.name).await;
}
},
// 101 - Impermissible trigger values in JSON
101 => {
println!("Impermissible trigger values in JSON");
error!("Impermissible trigger values in JSON");
if is_active(&proc.name).await {
terminate_process(&proc.name).await;
}
@ -308,6 +342,7 @@ async fn unfreeze_process(name: &str) {
}
async fn restart_process(name: &str, path: &str) -> Result<(), CustomError> {
terminate_process(name).await;
tokio::time::sleep(Duration::from_millis(100)).await;
return start_process(name, path).await;
}
@ -318,7 +353,7 @@ async fn start_process(name: &str, path: &str) -> Result<(), CustomError> {
match command.spawn() {
Ok(_) => {
println!("Process {} is running now!", name);
warn!("Process {} is running now!", name);
Ok(())
},
Err(_) => {
@ -447,7 +482,7 @@ async fn service_handler(name: &str, services: &Vec<Services>, tx: Arc<mpsc::Sen
if !is_active(name).await || is_frozen(name).await {
return Err(CustomError::Fatal);
}
println!("Service {}:{} is unreachable for process {}", &serv.hostname, &serv.port, &name);
error!("Service {}:{} is unreachable for process {}", &serv.hostname, &serv.port, &name);
match serv.triggers.on_lost.as_str() {
"stay" => {
},
@ -488,10 +523,10 @@ async fn looped_service_connecting(
if serv.triggers.wait == 0 {
loop {
tokio::time::sleep(Duration::from_secs(serv.triggers.delay.into())).await;
println!("Attempting to connect from {} process to {}:{}",&name, &serv.hostname, &serv.port );
warn!("Attempting to connect from {} process to {}:{}",&name, &serv.hostname, &serv.port );
match check_service(&serv.hostname, &serv.port).await {
Ok(_) => {
println!("Successfully connected to {} from {} process!", &serv.hostname, &name);
log::info!("Successfully connected to {} from {} process!", &serv.hostname, &name);
break;
},
Err(_) => {
@ -504,10 +539,10 @@ async fn looped_service_connecting(
let start = Instant::now();
while start.elapsed().as_secs() < serv.triggers.wait.into() {
tokio::time::sleep(Duration::from_secs(serv.triggers.delay.into())).await;
println!("Attempting to connect from {} process to {}:{}",&name, &serv.hostname, &serv.port );
warn!("Attempting to connect from {} process to {}:{}",&name, &serv.hostname, &serv.port );
match check_service(&serv.hostname, &serv.port).await {
Ok(_) => {
println!("SUCCESS!");
log::info!("Successfully connected to {} from {} process!", &serv.hostname, &name);
return Ok(());
},
Err(_) => {