Skip to main content

sqlite_graphrag/commands/
daemon.rs

1use crate::constants::DAEMON_IDLE_SHUTDOWN_SECS;
2use crate::errors::AppError;
3use crate::output;
4use crate::paths::AppPaths;
5
6#[derive(clap::Args)]
7pub struct DaemonArgs {
8    /// Idle timeout in seconds before the daemon auto-shuts down to release the embedding model.
9    /// Default 600s; raise for long-running batch ingestion to avoid cold-start overhead.
10    #[arg(long, default_value_t = DAEMON_IDLE_SHUTDOWN_SECS)]
11    pub idle_shutdown_secs: u64,
12    /// Send a health-check ping to a running daemon and exit. Returns NotFound (exit 4) if no daemon.
13    #[arg(long)]
14    pub ping: bool,
15    /// Request graceful shutdown of a running daemon. Returns NotFound (exit 4) if no daemon.
16    #[arg(long)]
17    pub stop: bool,
18    #[arg(long, help = "No-op; JSON is always emitted on stdout")]
19    pub json: bool,
20    #[arg(long, env = "SQLITE_GRAPHRAG_DB_PATH")]
21    pub db: Option<String>,
22}
23
24pub fn run(args: DaemonArgs) -> Result<(), AppError> {
25    let _ = args.json;
26    let paths = AppPaths::resolve(args.db.as_deref())?;
27    paths.ensure_dirs()?;
28
29    if args.ping {
30        let response = crate::daemon::try_ping(&paths.models)?
31            .ok_or_else(|| AppError::NotFound("daemon not running".to_string()))?;
32        output::emit_json(&response)?;
33        return Ok(());
34    }
35
36    if args.stop {
37        let response = crate::daemon::try_shutdown(&paths.models)?
38            .ok_or_else(|| AppError::NotFound("daemon not running".to_string()))?;
39        output::emit_json(&response)?;
40        return Ok(());
41    }
42
43    crate::daemon::run(&paths.models, args.idle_shutdown_secs)
44}