refactor(hive-c0re): shared sqlite open helper with busy timeout
one db::open owns the parent-dir + connection + busy_timeout dance for every host-side store (broker/approvals/questions/schedules/power in broker.sqlite, build_logs, audit_log); schema + migrations stay per store. same-file connections now wait out concurrent writers instead of risking SQLITE_BUSY.
This commit is contained in:
parent
604e1c2557
commit
380c6ad47f
8 changed files with 45 additions and 41 deletions
38
hive-c0re/src/db.rs
Normal file
38
hive-c0re/src/db.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
//! Shared sqlite connection setup for hive-c0re's host-side stores.
|
||||
//!
|
||||
//! Several modules keep their own tables — and their own
|
||||
//! `Mutex<Connection>` — in the coordinator DB
|
||||
//! (`db/broker.sqlite`: broker, approvals, operator questions,
|
||||
//! scheduled prompts, agent power) or in a sibling file under the same
|
||||
//! `db/` dir (`build_logs.sqlite`, `audit_log.sqlite`). The open dance
|
||||
//! is identical everywhere: ensure the parent dir exists, open the
|
||||
//! connection, set a busy timeout so concurrent same-process writers
|
||||
//! wait each other out instead of surfacing `SQLITE_BUSY`. This helper
|
||||
//! owns that dance; schema creation + column migrations stay with each
|
||||
//! store (they're per-table concerns).
|
||||
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use rusqlite::Connection;
|
||||
|
||||
/// How long a write waits on another connection's lock before erroring.
|
||||
/// Generous relative to the stores' tiny transactions — a timeout here
|
||||
/// means something is genuinely wedged, not ordinary contention.
|
||||
const BUSY_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
|
||||
/// Open a connection to the sqlite file at `path`, creating the parent
|
||||
/// directory if needed. `subsystem` labels error contexts (`"broker"`,
|
||||
/// `"approvals"`, …).
|
||||
pub fn open(path: &Path, subsystem: &str) -> Result<Connection> {
|
||||
if let Some(parent) = path.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.with_context(|| format!("create {subsystem} db parent {}", parent.display()))?;
|
||||
}
|
||||
let conn = Connection::open(path)
|
||||
.with_context(|| format!("open {subsystem} db {}", path.display()))?;
|
||||
conn.busy_timeout(BUSY_TIMEOUT)
|
||||
.with_context(|| format!("set {subsystem} busy_timeout"))?;
|
||||
Ok(conn)
|
||||
}
|
||||
Loading…
Reference in a new issue