refactor: per-agent state paths (/agents/{label}/state), centralize in paths.rs

This commit is contained in:
damocles 2026-05-16 14:16:25 +02:00
parent a82009cf8c
commit a6d1464071
10 changed files with 86 additions and 56 deletions

View file

@ -20,21 +20,18 @@ const CHANNEL_CAPACITY: usize = 256;
/// Max `LiveEvent`s the `Bus` returns from `history()` and keeps in
/// sqlite. Older rows are vacuumed on a periodic sweep.
const HISTORY_CAPACITY: usize = 2000;
/// Default sqlite db path. Lives under `/state/` so it survives
/// destroy/recreate but goes away on purge. Overridable via the
/// `HYPERHIVE_EVENTS_DB` env var (used in tests and one-shot tools).
const DEFAULT_EVENTS_DB: &str = "/state/hyperhive-events.sqlite";
/// Path to the persisted event db. Overridable via `HYPERHIVE_EVENTS_DB`
/// for dev / tests; otherwise derived from the agent's state dir.
fn events_db_path() -> PathBuf {
std::env::var_os("HYPERHIVE_EVENTS_DB")
.map_or_else(|| crate::paths::state_dir().join("hyperhive-events.sqlite"), PathBuf::from)
}
/// Persisted model name file. Same lifecycle as the events db —
/// survives destroy/recreate, gone on purge. Empty / missing file
/// falls back to `DEFAULT_MODEL`.
const DEFAULT_MODEL_FILE: &str = "/state/hyperhive-model";
/// Path to the persisted model file. Overridable via
/// `HYPERHIVE_MODEL_FILE` for dev / tests.
/// Path to the persisted model file. Overridable via `HYPERHIVE_MODEL_FILE`
/// for dev / tests; otherwise derived from the agent's state dir.
fn model_file_path() -> PathBuf {
std::env::var_os("HYPERHIVE_MODEL_FILE")
.map_or_else(|| PathBuf::from(DEFAULT_MODEL_FILE), PathBuf::from)
.map_or_else(|| crate::paths::state_dir().join("hyperhive-model"), PathBuf::from)
}
fn load_model() -> Option<String> {
@ -183,7 +180,7 @@ pub struct Bus {
tx: Arc<broadcast::Sender<LiveEvent>>,
/// Persistent event log. `None` only if opening the sqlite db failed
/// at construction — we keep going so the harness doesn't die on a
/// missing `/state/` mount in dev / test scenarios.
/// missing state dir mount in dev / test scenarios.
store: Option<Arc<EventStore>>,
/// Current turn-loop state + since-when (unix seconds).
state: Arc<Mutex<(TurnState, i64)>>,
@ -200,13 +197,11 @@ pub struct Bus {
}
impl Bus {
/// Open the default events db (`/state/hyperhive-events.sqlite`, or
/// `HYPERHIVE_EVENTS_DB`). On failure, fall back to a no-store bus —
/// the harness still works, just without persistent history.
/// Open the events db (path from `events_db_path()`). On failure, fall back
/// to a no-store bus — the harness still works, just without persistent history.
#[must_use]
pub fn new() -> Self {
let path = std::env::var_os("HYPERHIVE_EVENTS_DB")
.map_or_else(|| PathBuf::from(DEFAULT_EVENTS_DB), PathBuf::from);
let path = events_db_path();
let store = match EventStore::open(&path) {
Ok(s) => Some(Arc::new(s)),
Err(e) => {
@ -247,8 +242,8 @@ impl Bus {
}
/// Switch the model for future turns. The current turn (if any)
/// keeps the model it was already running. Persisted to
/// `/state/hyperhive-model` so the override survives harness
/// keeps the model it was already running. Persisted to the agent's
/// state dir (`hyperhive-model`) so the override survives harness
/// restart and container rebuild (gone on `--purge`, matching
/// every other piece of agent state).
pub fn set_model(&self, name: impl Into<String>) {