mirror of
https://github.com/Noratrieb/service-manager.git
synced 2026-01-14 16:35:05 +01:00
optimize error handling
This commit is contained in:
parent
4a9990a9cd
commit
8de36860af
4 changed files with 62 additions and 55 deletions
|
|
@ -1,10 +1,9 @@
|
|||
use crate::model::config::Config;
|
||||
use crate::model::{AppState, Service, ServiceStatus};
|
||||
use crate::model::{AppState, Service, ServiceStatus, SmError, SmResult};
|
||||
use crate::{view, App};
|
||||
use crossterm::event;
|
||||
use crossterm::event::{Event, KeyCode};
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::io::{ErrorKind, Read, Write};
|
||||
use std::process::{Child, Command, Stdio};
|
||||
|
|
@ -18,7 +17,7 @@ const STDOUT_SEND_BUF_SIZE: usize = 512;
|
|||
|
||||
pub type StdoutSendBuf = ([u8; STDOUT_SEND_BUF_SIZE], usize);
|
||||
|
||||
pub fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<()> {
|
||||
pub fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> SmResult {
|
||||
loop {
|
||||
terminal.draw(|f| view::render_ui(f, &mut app))?;
|
||||
|
||||
|
|
@ -30,7 +29,7 @@ pub fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Resu
|
|||
Some(_) => app.leave_service(),
|
||||
None => break,
|
||||
},
|
||||
KeyCode::Char('r') => app.run_service(),
|
||||
KeyCode::Char('r') => app.run_service()?,
|
||||
KeyCode::Down => app.next(),
|
||||
KeyCode::Up => app.previous(),
|
||||
KeyCode::Enter => app.select_service(),
|
||||
|
|
@ -87,19 +86,6 @@ impl App {
|
|||
for service in self.table.services.iter_mut() {
|
||||
while let Ok((buf, n)) = service.stdout_recv.try_recv() {
|
||||
service.stdout_buf.extend_from_slice(&buf[0..n]);
|
||||
|
||||
std::fs::write(
|
||||
format!(
|
||||
"debug/received_something_{}_{}.txt",
|
||||
&service.name,
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_millis()
|
||||
),
|
||||
&service.stdout_buf,
|
||||
)
|
||||
.expect("debug failed fuck");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -144,25 +130,26 @@ impl App {
|
|||
self.table.table_state.select(Some(i));
|
||||
}
|
||||
|
||||
fn run_service(&mut self) {
|
||||
fn run_service(&mut self) -> SmResult {
|
||||
if let Some(selected) = self.selected {
|
||||
self.start_service(selected)
|
||||
} else if let Some(selected) = self.table.table_state.selected() {
|
||||
self.start_service(selected)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn start_service(&mut self, service: usize) {
|
||||
fn start_service(&mut self, service: usize) -> SmResult {
|
||||
let service = &mut self.table.services[service];
|
||||
|
||||
*service.status.lock().expect("service.status lock poisoned") = ServiceStatus::Running;
|
||||
*service.status.lock()? = ServiceStatus::Running;
|
||||
|
||||
let stdout_send = service
|
||||
.stdout_send
|
||||
.lock()
|
||||
.expect("stdout_send lock poisoned")
|
||||
.lock()?
|
||||
.take()
|
||||
.expect("stdout_send has been stolen");
|
||||
.ok_or(SmError::StdioStolen)?;
|
||||
|
||||
let mut cmd = Command::new("sh");
|
||||
|
||||
|
|
@ -178,12 +165,14 @@ impl App {
|
|||
let mut buf = [0; STDOUT_SEND_BUF_SIZE];
|
||||
|
||||
let bytes = err.to_string();
|
||||
(&mut buf[..]).write_all(bytes.as_bytes()).expect("dont");
|
||||
|
||||
(&mut buf[..]).write_all(bytes.as_bytes())?;
|
||||
|
||||
stdout_send
|
||||
.send((buf, bytes.len()))
|
||||
.expect("failed to send stdout");
|
||||
return;
|
||||
.map_err(|_| SmError::FailedToSendStdio)?;
|
||||
|
||||
return Err(SmError::FailedToStartChild(err));
|
||||
}
|
||||
Ok(child) => child,
|
||||
};
|
||||
|
|
@ -196,6 +185,8 @@ impl App {
|
|||
Ok(_) => {}
|
||||
Err(e) => std::fs::write("error.txt", e.to_string()).unwrap(),
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
fn child_process_thread(
|
||||
|
|
@ -217,18 +208,6 @@ fn child_process_thread(
|
|||
match stdout.read(&mut stdout_buf) {
|
||||
Ok(0) => continue,
|
||||
Ok(n) => {
|
||||
// std::fs::write(
|
||||
// format!(
|
||||
// "debug/read_something_{}.txt",
|
||||
// std::time::SystemTime::now()
|
||||
// .duration_since(std::time::UNIX_EPOCH)
|
||||
// .unwrap()
|
||||
// .as_millis()
|
||||
// ),
|
||||
// &stdout_buf,
|
||||
// )
|
||||
// .ok();
|
||||
|
||||
stdout_send
|
||||
.send((stdout_buf, n))
|
||||
.map_err(|_| io::Error::from(io::ErrorKind::Other))?;
|
||||
|
|
|
|||
11
src/main.rs
11
src/main.rs
|
|
@ -7,9 +7,7 @@ use crossterm::execute;
|
|||
use crossterm::terminal::{
|
||||
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
|
||||
};
|
||||
use std::io::{ErrorKind, Read, StdoutLock};
|
||||
use std::process::Stdio;
|
||||
use std::time::Duration;
|
||||
use std::io::StdoutLock;
|
||||
use std::{env, fs, io};
|
||||
use tui::backend::CrosstermBackend;
|
||||
use tui::Terminal;
|
||||
|
|
@ -44,7 +42,10 @@ or use the environment variable SERVICE_MANAGER_CONFIG_PATH"
|
|||
let stdout = io::stdout();
|
||||
let stdout = stdout.lock();
|
||||
|
||||
let mut terminal = setup_terminal(stdout).expect("failed to setup terminal");
|
||||
let mut terminal = setup_terminal(stdout).unwrap_or_else(|e| {
|
||||
eprintln!("error: failed to setup terminal: {}", e);
|
||||
std::process::exit(1);
|
||||
});
|
||||
|
||||
// create app and run it
|
||||
let app = App::new(config);
|
||||
|
|
@ -53,7 +54,7 @@ or use the environment variable SERVICE_MANAGER_CONFIG_PATH"
|
|||
let res = controller::run_app(&mut terminal, app);
|
||||
|
||||
if let Err(err) = res {
|
||||
println!("{:?}", err)
|
||||
println!("error: {}", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
49
src/model.rs
49
src/model.rs
|
|
@ -1,12 +1,11 @@
|
|||
use crate::controller::StdoutSendBuf;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::io::Error;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{mpsc, Mutex};
|
||||
use tui::widgets::TableState;
|
||||
|
||||
pub use error::{SmError, SmResult};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct App {
|
||||
pub table: AppState,
|
||||
|
|
@ -55,16 +54,44 @@ pub mod config {
|
|||
pub env: Option<HashMap<String, String>>,
|
||||
}
|
||||
}
|
||||
mod error {
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::io;
|
||||
use std::sync::PoisonError;
|
||||
|
||||
pub type SmResult = Result<(), SmError>;
|
||||
pub type SmResult = Result<(), SmError>;
|
||||
|
||||
pub enum SmError {
|
||||
Io(io::Error),
|
||||
MutexPoisoned,
|
||||
}
|
||||
pub enum SmError {
|
||||
Io(io::Error),
|
||||
FailedToStartChild(io::Error),
|
||||
MutexPoisoned,
|
||||
StdioStolen,
|
||||
FailedToSendStdio,
|
||||
}
|
||||
|
||||
impl From<io::Error> for SmError {
|
||||
fn from(e: Error) -> Self {
|
||||
Self::Io(e)
|
||||
impl From<io::Error> for SmError {
|
||||
fn from(e: io::Error) -> Self {
|
||||
Self::Io(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<std::sync::PoisonError<T>> for SmError {
|
||||
fn from(_: PoisonError<T>) -> Self {
|
||||
Self::MutexPoisoned
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SmError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Io(e) => Display::fmt(e, f),
|
||||
SmError::MutexPoisoned => f.write_str("Mutex was poisoned. This is a bug."),
|
||||
SmError::StdioStolen => f.write_str("Stdio was stolen. This is a bug."),
|
||||
SmError::FailedToStartChild(e) => write!(f, "Failed to start child process: {}", e),
|
||||
SmError::FailedToSendStdio => {
|
||||
f.write_str("Failed to send stdio to display thread. This is a bug.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ fn render_table<B: Backend>(f: &mut Frame<B>, state: &mut AppState, area: Rect)
|
|||
service
|
||||
.status
|
||||
.lock()
|
||||
.expect("service.status lock poisoned")
|
||||
.expect("service.status lock poisoned") // returning result here is too much effort
|
||||
.to_string(),
|
||||
),
|
||||
];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue