pub struct SqliteStore { /* private fields */ }Expand description
The rusqlite-backed Store.
One connection behind a mutex. SQLite serialises writers anyway, so a
connection pool would buy concurrency the database does not offer; what the
mutex buys is Sync, so the agent can hold one handle across tasks.
Opened with synchronous = FULL and a request for WAL. FULL because this
journal exists precisely to survive an unclean stop: a handful of fsyncs per
runner attempt is not a cost worth trading for the chance of losing the last
write before a power cut. WAL so that a reader — the TUI — does not block the
agent’s journal writes.
The WAL half is a request, not a guarantee, which is why
Self::journal_mode exists to report what actually happened. SQLite falls
back to delete where the directory cannot host WAL’s shared-memory file,
and says so in the pragma’s return row rather than by failing.
Implementations§
Source§impl SqliteStore
impl SqliteStore
Sourcepub fn open(path: impl AsRef<Path>) -> Result<Self, StoreError>
pub fn open(path: impl AsRef<Path>) -> Result<Self, StoreError>
Open (or create) the database at path and migrate it to
SCHEMA_VERSION.
The path is used exactly as given. Resolving the platform
application-data directory and creating it is d1’s job; a missing parent
directory is reported rather than created.
§Errors
StoreError::Open when the file cannot be opened,
StoreError::SchemaTooNew when the database came from a newer build,
StoreError::Migration when a step fails.
Sourcepub fn open_in_memory() -> Result<Self, StoreError>
pub fn open_in_memory() -> Result<Self, StoreError>
An anonymous in-memory database, migrated to SCHEMA_VERSION.
For tests and for a dry run. It is private to this one connection — a
second open_in_memory is a different database — so it cannot stand in
for a file store in a test about two concurrent writers.
§Errors
Sourcepub const fn schema_version(&self) -> u32
pub const fn schema_version(&self) -> u32
The schema version this database is at.
Sourcepub fn journal_mode(&self) -> &str
pub fn journal_mode(&self) -> &str
The journal mode this database is actually in, lowercased by SQLite.
wal for a healthy file store, memory for an in-memory one, and
something else — delete, usually — where the directory cannot host
WAL’s shared-memory file. That last case is not a failure but it does
mean a reader blocks the agent’s journal writes, so it is worth showing
an operator rather than assuming.
Sourcepub fn readers_do_not_block_writers(&self) -> bool
pub fn readers_do_not_block_writers(&self) -> bool
Whether a reader can read this database without blocking the agent’s writes.
True exactly when Self::journal_mode is wal. An in-memory store is
not included: it is private to one connection, so the question does
not arise for it.
Sourcepub fn path(&self) -> Option<&Path>
pub fn path(&self) -> Option<&Path>
The path this store was opened from, or None for an in-memory one.
Sourcepub fn clock_skew_repairs(&self) -> u64
pub fn clock_skew_repairs(&self) -> u64
How many attempt timestamps this store has repaired for backwards clock movement since it was opened.
See SqliteStore::normalise for what is repaired and why. A non-zero
value means this machine’s clock stepped backwards while an attempt was in
flight; each repair is also logged at warn.
Sourcepub fn dump_text(&self) -> Result<String, StoreError>
pub fn dump_text(&self) -> Result<String, StoreError>
Every row of every table, as text, in a deterministic order.
Two callers. An operator support bundle, and the security gate: the
Definition of Done requires that “a grep of every fixture database and its
dump finds no token-shaped value”, and a dump produced here is a testable
artifact where a sqlite3 .dump invocation in a shell script is not.
This is safe to attach to a bug report because no column carries a credential, not because anything here redacts one. If a column ever does, this function becomes a disclosure and the schema is what has to change.
§Errors
StoreError::Sqlite on an I/O failure.
Trait Implementations§
Source§impl Debug for SqliteStore
impl Debug for SqliteStore
Source§impl Store for SqliteStore
impl Store for SqliteStore
Source§fn put_host(&self, host: &Host) -> Result<(), StoreError>
fn put_host(&self, host: &Host) -> Result<(), StoreError>
Source§fn host(&self, id: HostId) -> Result<Option<Host>, StoreError>
fn host(&self, id: HostId) -> Result<Option<Host>, StoreError>
Source§fn set_runner_root_override(
&self,
id: HostId,
expected: Option<&LocalAbsolutePath>,
new_root: Option<&LocalAbsolutePath>,
expected_uncleaned: u16,
) -> Result<(), StoreError>
fn set_runner_root_override( &self, id: HostId, expected: Option<&LocalAbsolutePath>, new_root: Option<&LocalAbsolutePath>, expected_uncleaned: u16, ) -> Result<(), StoreError>
Source§fn insert_policy(&self, policy: &ScalePolicy) -> Result<(), StoreError>
fn insert_policy(&self, policy: &ScalePolicy) -> Result<(), StoreError>
Source§fn update_policy(
&self,
policy: &ScalePolicy,
expected_revision: u64,
) -> Result<(), StoreError>
fn update_policy( &self, policy: &ScalePolicy, expected_revision: u64, ) -> Result<(), StoreError>
Source§fn update_policy_confirming_active_count(
&self,
policy: &ScalePolicy,
expected_revision: u64,
expected_active: u16,
) -> Result<(), StoreError>
fn update_policy_confirming_active_count( &self, policy: &ScalePolicy, expected_revision: u64, expected_active: u16, ) -> Result<(), StoreError>
Store::attempts_for_policy and Store::update_policy
does not satisfy this contract.Source§fn update_policy_confirming_uncleaned_count(
&self,
policy: &ScalePolicy,
expected_revision: u64,
expected_uncleaned: u16,
) -> Result<(), StoreError>
fn update_policy_confirming_uncleaned_count( &self, policy: &ScalePolicy, expected_revision: u64, expected_uncleaned: u16, ) -> Result<(), StoreError>
Source§fn remove_policy(
&self,
id: PolicyId,
expected_revision: u64,
) -> Result<(), StoreError>
fn remove_policy( &self, id: PolicyId, expected_revision: u64, ) -> Result<(), StoreError>
Source§fn policy(&self, id: PolicyId) -> Result<Option<ScalePolicy>, StoreError>
fn policy(&self, id: PolicyId) -> Result<Option<ScalePolicy>, StoreError>
Source§fn policies(&self) -> Result<Vec<ScalePolicy>, StoreError>
fn policies(&self) -> Result<Vec<ScalePolicy>, StoreError>
Source§fn record_attempt(&self, attempt: &RunnerAttempt) -> Result<(), StoreError>
fn record_attempt(&self, attempt: &RunnerAttempt) -> Result<(), StoreError>
Source§fn attempt(&self, id: AttemptId) -> Result<Option<RunnerAttempt>, StoreError>
fn attempt(&self, id: AttemptId) -> Result<Option<RunnerAttempt>, StoreError>
Source§fn attempts(&self) -> Result<Vec<RunnerAttempt>, StoreError>
fn attempts(&self) -> Result<Vec<RunnerAttempt>, StoreError>
e3’s startup
recovery. Read more