From c8b84223e76a03f1e73e13491ecb7261a8035fb8 Mon Sep 17 00:00:00 2001 From: rasul Date: Sat, 26 Oct 2019 08:34:42 -0500 Subject: [PATCH] more code organization --- src/app.rs | 15 +++++- src/apps.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 130 +++------------------------------------------------- 3 files changed, 132 insertions(+), 124 deletions(-) create mode 100644 src/apps.rs diff --git a/src/app.rs b/src/app.rs index 5c7465f..85a6e57 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,4 +1,4 @@ -use std::process::Command; +use std::process::{Command, ExitStatus}; use crate::result::Result; @@ -40,4 +40,17 @@ impl App { Err(e) => Err(Box::from(e)), } } + + pub fn handle_exit(&self, status: ExitStatus) -> bool { + if status.success() { + info!("application exited: {}", &self.name); + self.restart_on_success.unwrap_or(false) + } else if let Some(code) = status.code() { + info!("application failed: {} ({})", &self.name, code); + self.restart_on_failure.unwrap_or(false) + } else { + info!("application terminated: {}", &self.name); + self.restart_on_terminate.unwrap_or(false) + } + } } diff --git a/src/apps.rs b/src/apps.rs new file mode 100644 index 0000000..83a8076 --- /dev/null +++ b/src/apps.rs @@ -0,0 +1,111 @@ +use std::fs::File; +use std::io::Read; +use std::path::PathBuf; + +use crate::app::App; +use crate::proc::Proc; +use crate::result::Result; + +#[derive(Debug, Deserialize)] +pub struct Apps { + pub app: Vec, +} + +impl Apps { + pub fn load>(p: T) -> Result { + let mut file = File::open(p.into())?; + let mut buf = String::new(); + file.read_to_string(&mut buf)?; + Ok(toml::from_str(&buf)?) + } + + pub fn apps(&self) -> Vec { + self.app.clone() + } + + pub fn start(&self) -> (Vec, Option) { + let mut procs: Vec = Vec::new(); + let mut holds: Option = None; + + for app in self.apps() { + if app.wait.unwrap_or(false) { + if let Err(e) = app.wait_start() { + error!("app failed to start: {}: {:?}", &app.name, e); + } + } else { + let name = app.name.clone(); + match Proc::start(app) { + Ok(proc) => { + if proc.app.hold.unwrap_or(false) { + holds = Some(holds.unwrap_or(0) + 1); + } + procs.push(proc); + } + Err(e) => error!("app failed to start: {}: {:?}", name, e), + }; + } + } + + (procs, holds) + } + + pub fn run(&self, procs: Vec, holds: Option) -> Result<()> { + let mut procs = procs; + let mut holds = holds; + + if holds.unwrap_or(0) < 1 { + error!("no holds configured"); + return Ok(()); + } + + while holds > Some(0) { + let mut newprocs: Vec = Vec::new(); + + while let Some(mut proc) = procs.pop() { + match proc.child.try_wait() { + Ok(Some(status)) => { + let hold = proc.app.hold.unwrap_or(false); + if proc.app.handle_exit(status) { + let name = proc.app.name.clone(); + match Proc::start(proc.app) { + Ok(p) => newprocs.push(p), + Err(e) => { + error!("error restarting {}: {:?}", name, e); + if hold { + holds = Some(holds.unwrap_or(0) - 1); + } + } + }; + } else if hold { + holds = Some(holds.unwrap_or(0) - 1); + } + } + Ok(None) => { + if let Some(s) = &proc.check_stdout() { + for line in s.lines() { + info!("[{}] stdout: {}", &proc.app.name, line); + } + } + if let Some(s) = &proc.check_stderr() { + for line in s.lines() { + info!("[{}] stderr: {}", &proc.app.name, line); + } + } + newprocs.push(proc); + } + Err(e) => error!("error: {:?}", e), + } + } + procs = newprocs; + } + + info!("shutting down"); + for mut proc in procs { + info!("stopping {}", &proc.app.name); + let _ = proc.child.kill(); + } + + Ok(()) + } + +} diff --git a/src/main.rs b/src/main.rs index b41c2cc..6924bf2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,144 +7,28 @@ extern crate serde_derive; extern crate toml; mod app; +mod apps; mod proc; mod result; -use std::fs::File; -use std::io::Read; -use std::path::PathBuf; -use std::process::ExitStatus; - -use app::App; -use proc::Proc; +use apps::Apps; use result::Result; -#[derive(Debug, Deserialize)] -struct Config { - app: Vec, -} - -impl Config { - fn load>(p: T) -> Result { - let mut file = File::open(p.into())?; - let mut buf = String::new(); - file.read_to_string(&mut buf)?; - Ok(toml::from_str(&buf)?) - } - - fn apps(&self) -> Vec { - self.app.clone() - } -} - fn main() { if let Err(e) = rag::init() { println!("FATAL: Error initializing logger: {:?}", e); std::process::exit(1); } - if let Err(e) = run() { + if let Err(e) = startup() { error!("FATAL: {:?}", e); std::process::exit(1); } } -fn start_apps(apps: Vec) -> (Vec, Option) { - let mut procs: Vec = Vec::new(); - let mut holds: Option = None; - - for app in apps { - if app.wait.unwrap_or(false) { - if let Err(e) = app.wait_start() { - error!("app failed to start: {}: {:?}", &app.name, e); - } - } else { - let name = app.name.clone(); - match Proc::start(app) { - Ok(proc) => { - if proc.app.hold.unwrap_or(false) { - holds = Some(holds.unwrap_or(0) + 1); - } - procs.push(proc); - } - Err(e) => error!("app failed to start: {}: {:?}", name, e), - }; - } - } - - (procs, holds) -} - -fn run() -> Result<()> { - let config = Config::load("sup.toml")?; - info!("loaded config: sup.toml"); - - let (mut procs, mut holds) = start_apps(config.apps()); - - if holds.unwrap_or(0) < 1 { - error!("no holds configured"); - return Ok(()); - } - - while holds > Some(0) { - let mut newprocs: Vec = Vec::new(); - - while let Some(mut proc) = procs.pop() { - match proc.child.try_wait() { - Ok(Some(status)) => { - let hold = proc.app.hold.unwrap_or(false); - if handle_exit(&proc.app, status) { - let name = proc.app.name.clone(); - match Proc::start(proc.app) { - Ok(p) => newprocs.push(p), - Err(e) => { - error!("error restarting {}: {:?}", name, e); - if hold { - holds = Some(holds.unwrap_or(0) - 1); - } - } - }; - } else if hold { - holds = Some(holds.unwrap_or(0) - 1); - } - } - Ok(None) => { - if let Some(s) = &proc.check_stdout() { - for line in s.lines() { - info!("[{}] stdout: {}", &proc.app.name, line); - } - } - if let Some(s) = &proc.check_stderr() { - for line in s.lines() { - info!("[{}] stderr: {}", &proc.app.name, line); - } - } - newprocs.push(proc); - } - Err(e) => error!("error: {:?}", e), - } - } - procs = newprocs; - } - - info!("shutting down"); - for mut proc in procs { - info!("stopping {}", &proc.app.name); - let _ = proc.child.kill(); - } - +fn startup() -> Result<()> { + let apps = Apps::load("sup.toml")?; + let (procs, holds) = apps.start(); + apps.run(procs, holds)?; Ok(()) } - -fn handle_exit(app: &App, status: ExitStatus) -> bool { - if status.success() { - info!("application exited: {}", &app.name); - app.restart_on_success.unwrap_or(false) - } else if let Some(code) = status.code() { - info!("application failed: {} ({})", &app.name, code); - app.restart_on_failure.unwrap_or(false) - } else { - info!("application terminated: {}", &app.name); - app.restart_on_terminate.unwrap_or(false) - } -}