olai_stack_state/lib.rs
1//! The shared trestle state store.
2//!
3//! One SQLite database under the [trestle home](trestle_home) (`$TRESTLE_HOME`, else the
4//! platform data directory), shared by the `trestle` CLI and the desktop app. It holds:
5//!
6//! - [`Workspace`]s: sets of environments sharing a host, with their [`VarSet`]s.
7//! - [`Environment`]s: an editable [`Draft`] (the placement-free `env.toml`, the
8//! `module.yaml` texts it lists, vars) and a head.
9//! - [`Revision`]s: numbered, immutable snapshots of a draft with a digest. Nothing in the
10//! API changes one, and the database refuses an update.
11//! - [`Instance`]s: a revision to run, whether it should run, overrides and overlay sources.
12//! - [`SlotLease`]s: host-wide, so two instances never share a slot whatever their
13//! workspace (slots per workspace clashed across workspaces).
14//!
15//! Secrets are stored as [`SecretRef`]s only; their values stay with their provider.
16//!
17//! Several processes use the store at once: writes are serialized (a writer waits for
18//! another's), and a [`Watcher`] notices commits made elsewhere. A store with a newer schema
19//! than this crate knows is refused ([`Error::UnsupportedVersion`]).
20//!
21//! `trestle-workspace.toml` and environment directories stay as an exchange format:
22//! [`Store::import_workspace`] drops placement (the store leases slots itself), and
23//! [`Store::export_instances`] writes the instances' slots, so the exported directory runs
24//! with `docker compose up` like any workspace.
25//!
26//! ```no_run
27//! use olai_stack_state::{Draft, Store};
28//! use olai_stack_topology::{EnvManifest, PlanCtx, Selection};
29//!
30//! # fn run() -> olai_stack_state::Result<()> {
31//! let store = Store::open_default()?;
32//! let ws = store.create_workspace("demo", false)?;
33//! let manifest = EnvManifest::new(Selection::modules(["unity-catalog"]), PlanCtx::default());
34//! let env = store.create_environment(&ws.id, "dev", Draft::new(manifest))?;
35//! let rev = store.commit_draft(&env.id)?;
36//! let instance = store.create_instance(&env.id, rev.number())?;
37//! let lease = store.lease_slot(&instance.id)?;
38//! println!("dev r{} on slot {}", rev.number(), lease.slot);
39//! # Ok(())
40//! # }
41//! ```
42
43mod error;
44mod model;
45mod store;
46mod transfer;
47mod watch;
48
49pub use error::{Error, Result};
50pub use model::{
51 Desired, Draft, Environment, EnvironmentId, Instance, InstanceId, Revision, SecretRef,
52 SlotLease, VarSet, VarValue, Workspace, WorkspaceId,
53};
54pub use store::{DB_FILE, SCHEMA_VERSION, Store, TRESTLE_HOME_VAR, trestle_home};
55pub use transfer::{ENV_FILE, read_env_dir};
56pub use watch::Watcher;