use crate::types::{ExecSession, PendingContainer};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Mutex;
const PENDING_DIR: &str = "/run/pelagos-dockerd/pending";
#[derive(Clone)]
pub struct AppState {
inner: Arc<Inner>,
}
struct Inner {
exec_sessions: Mutex<HashMap<String, ExecSession>>,
completed_execs: Mutex<HashMap<String, i64>>,
pub pelagos_bin: String,
}
impl AppState {
#[allow(dead_code)]
pub fn new() -> Self {
Self::new_with_bin("pelagos".to_string())
}
pub fn new_with_bin(pelagos_bin: String) -> Self {
let _ = std::fs::create_dir_all(PENDING_DIR);
Self {
inner: Arc::new(Inner {
exec_sessions: Mutex::new(HashMap::new()),
completed_execs: Mutex::new(HashMap::new()),
pelagos_bin,
}),
}
}
pub fn pelagos_bin(&self) -> &str {
&self.inner.pelagos_bin
}
pub async fn add_exec(&self, id: String, session: ExecSession) {
self.inner.exec_sessions.lock().await.insert(id, session);
}
pub async fn get_exec(&self, id: &str) -> Option<ExecSession> {
self.inner.exec_sessions.lock().await.get(id).cloned()
}
#[allow(dead_code)]
pub async fn remove_exec(&self, id: &str) {
self.inner.exec_sessions.lock().await.remove(id);
}
pub async fn complete_exec(&self, id: String, exit_code: i64) {
self.inner.exec_sessions.lock().await.remove(&id);
self.inner
.completed_execs
.lock()
.await
.insert(id, exit_code);
}
pub async fn get_completed_exec(&self, id: &str) -> Option<i64> {
self.inner.completed_execs.lock().await.get(id).copied()
}
}
pub fn save_pending(c: &PendingContainer) -> std::io::Result<()> {
let _ = std::fs::create_dir_all(PENDING_DIR);
let path = format!("{}/{}.json", PENDING_DIR, c.name);
let json = serde_json::to_string(c)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
std::fs::write(path, json)
}
pub fn load_pending(name: &str) -> std::io::Result<PendingContainer> {
let path = format!("{}/{}.json", PENDING_DIR, name);
let data = std::fs::read_to_string(&path)?;
serde_json::from_str(&data).map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
}
pub fn remove_pending(name: &str) {
let _ = std::fs::remove_file(format!("{}/{}.json", PENDING_DIR, name));
}
pub fn list_pending() -> Vec<PendingContainer> {
let Ok(entries) = std::fs::read_dir(PENDING_DIR) else {
return Vec::new();
};
entries
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().map(|x| x == "json").unwrap_or(false))
.filter_map(|e| {
std::fs::read_to_string(e.path())
.ok()
.and_then(|d| serde_json::from_str(&d).ok())
})
.collect()
}