Files
zesdex/apps/interfaces/daemon/src/server.rs
T

64 lines
2.4 KiB
Rust
Raw Normal View History

//! Daemon server — owns the agent state, listens on a per-session Unix
//! socket, and drives one attached client at a time.
//!
//! Flow: `run_daemon()` creates a session + lock → binds a Unix socket
//! under `<store>/run/<session_id>.sock` → blocks for a single client to
//! `accept()` → loops reading `ClientRequest`s, translating each into
//! `Action`(s) via the same `handle_key`/`apply_action` path the
//! single-process mode uses, then pushes a full state update back →
//! on `Close` or client disconnect, cleans up the socket file, saves
//! settings, and releases the lock.
//!
//! Why: reuses `crate::handler::handle_key` by synthesising a
//! `crossterm::KeyEvent` from the IPC `KeyAction`, so daemon and
//! single-process modes share identical key-handling logic.
use anyhow::Result;
use zesdex_infrastructure::ipc::server::IpcServer;
use crate::handler::handle_daemon_client;
use crate::state::create_session;
/// Run zesdex as a background daemon: owns the agent state, listens on a
/// per-session Unix socket, and drives one attached client.
///
/// Flow: create session + lock it → bind a Unix socket under
/// `<store>/run/<session_id>.sock` → block for a single client to
/// `accept()` → loop reading `ClientRequest`s, translating each into
/// `Action`(s) → on `Close` or client disconnect, clean up the socket file,
/// save settings, and release the lock.
pub fn run_daemon() -> Result<()> {
tracing::info!("starting daemon process");
let (store, _session_lock_guard, mut state, _rt) = create_session()?;
let run_dir = store.base_dir.join("run");
std::fs::create_dir_all(&run_dir)?;
let socket_path = run_dir.join(format!("{}.sock", state.session_id));
let addr = socket_path.to_string_lossy().to_string();
let server = IpcServer::bind_unix(&addr)?;
tracing::info!("daemon listening on {addr}");
loop {
let conn = match server.accept() {
Ok(c) => c,
Err(e) => {
tracing::error!("daemon accept error: {e}");
break;
}
};
tracing::info!("daemon client connected");
if let Err(e) = handle_daemon_client(conn, &mut state) {
tracing::error!("daemon error handling client: {e}");
}
tracing::info!("daemon client disconnected");
state.save_settings();
}
let _ = std::fs::remove_file(&socket_path);
Ok(())
}