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, the time they
10//! were committed and an optional message. Nothing in the API changes one, and the
11//! database refuses an update.
12//! - [`Instance`]s: a revision to run, whether it should run, overrides and the overlay
13//! [sources](SourceBinding) it takes.
14//! - [`SlotLease`]s: host-wide, so two instances never share a slot whatever their
15//! workspace (slots per workspace clashed across workspaces).
16//!
17//! Secrets are stored as [`SecretRef`]s only; their values stay with their provider.
18//!
19//! Workspaces and environments are renamed by id ([`Store::rename_workspace`],
20//! [`Store::rename_environment`]), keeping their revisions. A rename, like a change of the
21//! workspace's mesh ([`Store::set_mesh`]), waits until no instance of it is left
22//! ([`Error::HasInstances`]): Docker holds an instance's containers and volumes under names
23//! derived from the workspace and environment names.
24//!
25//! Several processes use the store at once: writes are serialized (a writer waits for
26//! another's), and a [`Watcher`] notices commits made elsewhere. A store with a newer schema
27//! than this crate knows is refused ([`Error::UnsupportedVersion`]).
28//!
29//! `trestle-workspace.toml` and environment directories stay as an exchange format:
30//! [`Store::import_workspace`] drops placement (the store leases slots itself), and
31//! [`Store::export_instances`] and [`Store::export_workspace`] write slots, so the exported
32//! directory runs with `docker compose up` like any workspace.
33//!
34//! ```no_run
35//! use olai_stack_state::{Draft, Store};
36//! use olai_stack_topology::{EnvManifest, PlanCtx, Selection};
37//!
38//! # fn run() -> olai_stack_state::Result<()> {
39//! let store = Store::open_default()?;
40//! let ws = store.create_workspace("demo", false)?;
41//! let manifest = EnvManifest::new(Selection::modules(["unity-catalog"]), PlanCtx::default());
42//! let env = store.create_environment(&ws.id, "dev", Draft::new(manifest))?;
43//! let rev = store.commit_draft(&env.id)?;
44//! let instance = store.create_instance(&env.id, rev.number())?;
45//! let lease = store.lease_slot(&instance.id)?;
46//! println!("dev r{} on slot {}", rev.number(), lease.slot);
47//! # Ok(())
48//! # }
49//! ```
50
51mod error;
52mod model;
53mod store;
54mod transfer;
55mod watch;
56
57pub use error::{Error, Result};
58pub use model::{
59 Desired, Draft, Environment, EnvironmentId, Instance, InstanceId, Revision, SecretRef,
60 SlotLease, SourceBinding, VarScope, VarSet, VarValue, Workspace, WorkspaceId,
61};
62pub use store::{DB_FILE, SCHEMA_VERSION, Store, TRESTLE_HOME_VAR, trestle_home};
63pub use transfer::{ENV_FILE, read_env_dir};
64pub use watch::Watcher;