use crate::process::Process;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::io::{BufRead, BufReader, Write};
use std::os::unix::net::UnixStream;
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "cmd", rename_all = "snake_case")]
pub enum Request {
Start {
name: String,
command: String,
cwd: String,
env: HashMap<String, String>,
max_restarts: u32,
},
Stop { name_or_id: String },
Restart { name_or_id: String },
Delete { name_or_id: String },
List,
Logs { name_or_id: String, lines: usize },
Show { name_or_id: String },
Save,
Resurrect,
Health,
Shutdown,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Response {
pub success: bool,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub processes: Option<Vec<Process>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub process: Option<Process>,
#[serde(skip_serializing_if = "Option::is_none")]
pub logs: Option<String>,
}
impl Response {
pub fn ok(message: impl Into<String>) -> Self {
Self {
success: true,
message: message.into(),
processes: None,
process: None,
logs: None,
}
}
pub fn err(message: impl Into<String>) -> Self {
Self {
success: false,
message: message.into(),
processes: None,
process: None,
logs: None,
}
}
pub fn with_processes(mut self, procs: Vec<Process>) -> Self {
self.processes = Some(procs);
self
}
pub fn with_process(mut self, proc: Process) -> Self {
self.process = Some(proc);
self
}
pub fn with_logs(mut self, logs: String) -> Self {
self.logs = Some(logs);
self
}
}
pub fn send(request: &Request) -> Result<Response> {
let sock_path = crate::config::get().sock_path.clone();
let mut stream = UnixStream::connect(&sock_path).map_err(|e| {
anyhow::anyhow!(
"Cannot connect to daemon socket at {:?}: {}\n\
Hint: run `proses daemon start` first.",
sock_path,
e
)
})?;
let mut payload = serde_json::to_string(request)?;
payload.push('\n');
stream
.write_all(payload.as_bytes())
.context("Failed to write request to daemon socket")?;
stream
.flush()
.context("Failed to flush request to daemon socket")?;
let mut line = String::new();
BufReader::new(&stream)
.read_line(&mut line)
.context("Failed to read response from daemon socket")?;
let response: Response =
serde_json::from_str(line.trim()).context("Failed to deserialise daemon response")?;
Ok(response)
}