pub mod builtins;
pub mod catalog;
pub mod client;
pub mod export;
pub mod firstrun;
pub mod fsnotify;
pub mod history;
pub mod ipc;
pub mod log;
pub mod ops;
pub mod paths;
pub mod pidlock;
pub mod pubsub;
pub mod server;
pub mod shard;
pub mod source_resolver;
pub mod state;
pub mod walk;
pub mod zask;
pub mod zshrc_analysis;
pub mod zsync;
pub use ipc::{Event, Frame, Hello, ProtocolVersion, Welcome, PROTOCOL_VERSION};
pub use paths::CachePaths;
pub type Result<T> = std::result::Result<T, DaemonError>;
#[derive(thiserror::Error, Debug)]
pub enum DaemonError {
#[error("io: {0}")]
Io(#[from] std::io::Error),
#[error("json: {0}")]
Json(#[from] serde_json::Error),
#[error("nix: {0}")]
Nix(#[from] nix::Error),
#[error("rusqlite: {0}")]
Sqlite(#[from] rusqlite::Error),
#[error("singleton: another daemon is running (pid {0})")]
AlreadyRunning(i32),
#[error("protocol: client v{client} incompatible with daemon v{daemon}")]
ProtocolMismatch { client: u32, daemon: u32 },
#[error("protocol: malformed handshake")]
BadHandshake,
#[error("protocol: frame too large ({size} > {max})")]
FrameTooLarge { size: usize, max: usize },
#[error("daemon: shutting down")]
Shutdown,
#[error("op: unknown opcode {0:?}")]
UnknownOp(String),
#[error("op: bad args for {op}: {reason}")]
BadArgs { op: String, reason: String },
#[error("client: not connected to daemon")]
NotConnected,
#[error("client: timed out after {0:?}")]
Timeout(std::time::Duration),
#[error("{0}")]
Other(String),
}
impl DaemonError {
pub fn other<S: Into<String>>(msg: S) -> Self {
Self::Other(msg.into())
}
}
pub fn run() -> Result<()> {
let paths = paths::CachePaths::resolve()?;
paths.ensure_dirs()?;
let _log_guard = log::init(&paths)?;
tracing::info!(version = env!("CARGO_PKG_VERSION"), "zshrs-daemon starting");
let _pid_lock = pidlock::acquire(&paths)?;
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.thread_name("zshrs-daemon")
.build()?;
let result = rt.block_on(server::serve(paths.clone()));
tracing::info!("zshrs-daemon exiting");
result
}