blockworx/store/mod.rs
1//! The durable store: the `.bwx` container, the rev files that *are* the
2//! document, and the manifest that names them.
3//! Rationale: `docs/single-author-playbook.md` Phase 2, D1/D12 and D26;
4//! `docs/log-vs-snapshot.md` S3/S4.
5//!
6//! ```text
7//! Commit ──▶ Document ──▶ revs/{rev}.json.zst ──▶ one row of manifest.jsonl
8//! ```
9//!
10//! The rev files are authoritative and everything beside them is derived,
11//! so this module is written for one property: what the editor holds and
12//! what the files hold agree at every point a call can return. A rev lands
13//! and is fsync'd before the row that names it; loads verify every chain
14//! link and the head rev's own bytes before the document is shown; and the
15//! container gives up its lock rather than write into a history it has
16//! already lost track of.
17//!
18//! The row types, the rev encoding and the asset store are
19//! target-independent — Phase 8 reads the same text out of the browser's
20//! origin storage, and a session with no files stands its revs in memory —
21//! while the directory, the lock, and the store that owns them are
22//! native-only.
23
24pub mod assets;
25pub mod history;
26pub mod manifest;
27pub mod projection;
28pub mod record;
29pub mod revs;
30pub mod tags;
31
32#[cfg(not(target_arch = "wasm32"))]
33pub mod bundle;
34#[cfg(not(target_arch = "wasm32"))]
35pub mod container;
36#[cfg(not(target_arch = "wasm32"))]
37pub mod dump;
38#[cfg(not(target_arch = "wasm32"))]
39pub mod handle;
40#[cfg(not(target_arch = "wasm32"))]
41pub mod lock;
42#[cfg(not(target_arch = "wasm32"))]
43pub mod prefix;
44
45#[cfg(test)]
46pub(crate) mod tests;
47
48use blockworx_doc::{document::FoldError, rev::Rev, trail::UndoRefusal};
49
50/// Why a write did not happen. Target-independent because the editor's
51/// document handle ([`crate::doc::Doc`]) reports refusals in one spelling
52/// whether it is holding a container or an in-process session, and the web
53/// build has only the latter.
54#[derive(Debug, thiserror::Error)]
55pub enum Refusal {
56 #[error("this diagram is open read-only")]
57 ReadOnly,
58 #[error("this session has no diagram on disk to write")]
59 Detached,
60 #[error(transparent)]
61 Fold(#[from] FoldError),
62 #[error(transparent)]
63 Step(#[from] UndoRefusal),
64 #[error("this history holds no rev {}", .0.get())]
65 NoSuchRev(Rev),
66 #[error("the document at rev {} could not be read back: {why}", .at.get())]
67 Unreachable { at: Rev, why: String },
68 #[error("the row could not be appended: {0}")]
69 Append(std::io::Error),
70 #[error("the diagram could not be renamed: {0}")]
71 Rename(std::io::Error),
72 #[error("the diagram file could not be written: {0}")]
73 Projection(std::io::Error),
74}