kindling_server/config.rs
1//! Daemon configuration.
2
3use std::path::PathBuf;
4use std::time::Duration;
5
6/// Default idle timeout before the daemon shuts itself down (30 minutes).
7pub const DEFAULT_IDLE_TIMEOUT: Duration = Duration::from_secs(30 * 60);
8
9/// Which transport the daemon binds and serves the v1 HTTP API on.
10///
11/// Unix domain sockets are the default (and only authenticated) transport on
12/// Unix; Windows has no UDS so it falls back to loopback TCP, publishing the
13/// bound ephemeral port in a side-channel file ([`ServerConfig::port_path`]).
14///
15/// The variant set is platform-gated so each platform's `match` stays
16/// exhaustive: `Uds` exists only on Unix, `Tcp` everywhere. The Linux build
17/// keeps both so the TCP path can be exercised in tests (and is what real
18/// Windows uses by default).
19#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
20pub enum Transport {
21 /// Unix domain socket at [`ServerConfig::socket_path`] (Unix only; the
22 /// platform default there).
23 #[cfg(unix)]
24 #[cfg_attr(unix, default)]
25 Uds,
26 /// Loopback TCP on an ephemeral `127.0.0.1` port published to
27 /// [`ServerConfig::port_path`]. The platform default on non-Unix (Windows).
28 #[cfg_attr(not(unix), default)]
29 Tcp,
30}
31
32/// Runtime configuration for [`serve`](crate::serve).
33///
34/// Construct via [`ServerConfig::new`] for the default home-relative paths, or
35/// build the struct directly (tests inject a temp `kindling_home`, a unique
36/// `socket_path`, a unique `pid_path`, and a short `idle_timeout`).
37#[derive(Debug, Clone)]
38pub struct ServerConfig {
39 /// Unix domain socket to bind (`~/.kindling/kindling.sock` by default).
40 pub socket_path: PathBuf,
41 /// Root of per-project databases (`~/.kindling` by default). Each request's
42 /// `X-Kindling-Project` header routes to `kindling_home/projects/<hash>/…`.
43 pub kindling_home: PathBuf,
44 /// PID file written on startup (`~/.kindling/kindling.pid` by default).
45 pub pid_path: PathBuf,
46 /// File the TCP port is published to when [`Self::transport`] is
47 /// [`Transport::Tcp`] (`~/.kindling/kindling.port` by default). Written
48 /// after binding the ephemeral loopback port; removed on shutdown. Unused
49 /// for the UDS transport.
50 pub port_path: PathBuf,
51 /// Shut down after this much idle time (no in-flight and no recent
52 /// requests). Defaults to [`DEFAULT_IDLE_TIMEOUT`].
53 pub idle_timeout: Duration,
54 /// Transport to bind. Defaults to [`Transport::default`] (UDS on Unix, TCP
55 /// on Windows).
56 pub transport: Transport,
57}
58
59impl ServerConfig {
60 /// Build a config rooted at `kindling_home` with conventional file names.
61 pub fn new(kindling_home: PathBuf) -> Self {
62 Self {
63 socket_path: kindling_home.join("kindling.sock"),
64 pid_path: kindling_home.join("kindling.pid"),
65 port_path: kindling_home.join("kindling.port"),
66 kindling_home,
67 idle_timeout: DEFAULT_IDLE_TIMEOUT,
68 transport: Transport::default(),
69 }
70 }
71
72 /// Build a config from the default kindling home (`~/.kindling`).
73 ///
74 /// Returns `None` when no home directory can be determined (mirrors
75 /// [`kindling_store::default_kindling_home`]).
76 pub fn from_default_home() -> Option<Self> {
77 kindling_store::default_kindling_home().map(Self::new)
78 }
79}