salamander/lib.rs
1//! SalamanderDB — an embedded event-sourcing engine with instant recovery.
2//!
3//! DESIGN.md §1 — the append-only log is the only durable structure;
4//! everything else is a rebuildable projection.
5//!
6//! The engine is generic over its payload type: [`Salamander<B>`] frames,
7//! orders, and persists bodies of any [`Body`] type but never interprets
8//! them (P1 — "general engine underneath, agent memory as a labeled
9//! beachhead"). The agent vocabulary — [`agent::EventBody`],
10//! [`agent::SessionProjection`], `session_view`, `fork` — is a *provided
11//! module* over that engine, in [`agent`]. Agent users open an
12//! [`AgentDb`] and never see the type parameter.
13//!
14//! Phase 1 scope: log core, in-memory projections, full replay on open,
15//! time-travel, fork. See DESIGN.md and IMPLEMENTATION.md at the repo root.
16//!
17//! # Custom payloads
18//!
19//! Any serde-serializable, `Clone`, `'static` type is a valid payload —
20//! the agent vocabulary is just one choice. Define your own events and
21//! project them however you like:
22//!
23//! ```
24//! use salamander::{Event, Salamander};
25//! use serde::{Deserialize, Serialize};
26//!
27//! #[derive(Clone, Serialize, Deserialize)]
28//! enum Metric {
29//! Cpu(f64),
30//! Mem(u64),
31//! }
32//!
33//! # fn main() -> salamander::Result<()> {
34//! let dir = tempfile::tempdir().unwrap();
35//!
36//! let mut db: Salamander<Metric> = Salamander::open(dir.path())?;
37//! db.append("host-1", Metric::Cpu(0.7))?;
38//! db.append("host-1", Metric::Mem(2048))?;
39//! db.commit()?;
40//! drop(db); // release the single-writer lock before reopening
41//!
42//! // Reopen from disk and read the custom payloads straight back out.
43//! let db: Salamander<Metric> = Salamander::open(dir.path())?;
44//! let mut count = 0;
45//! db.replay("host-1", 0..db.head(), |_e: &Event<Metric>| count += 1)?;
46//! assert_eq!(count, 2);
47//! # Ok(())
48//! # }
49//! ```
50
51#![warn(missing_docs)]
52
53mod branch;
54mod commit;
55mod error;
56mod event;
57mod facade;
58mod log;
59mod migration;
60mod projection;
61mod snapshot;
62mod stream;
63
64pub mod agent;
65/// Low-level engine framing and codec types. Most users need only the
66/// types re-exported at the crate root (`BranchId`, `StreamId`,
67/// `EventType`, `CodecId`, …); the framing internals here are not a stable
68/// API.
69#[doc(hidden)]
70pub mod format;
71pub mod json;
72pub mod view;
73
74mod db;
75mod introspect;
76
77pub use branch::{BranchInfo, BranchName, BranchStatus, DEFAULT_BRANCH_NAME, MAX_LINEAGE_DEPTH};
78pub use commit::CommitPolicy;
79pub use error::{Result, SalamanderError};
80pub use event::{Body, Event};
81// The non-generic engine facade: the language-neutral boundary the
82// language bindings bind to, and the current home of the committed-batch
83// feed. Reachable (examples and `salamander-py` use these root paths) but
84// hidden from the documented surface — it is an advanced/plumbing layer,
85// not the stable typed Rust API, which is `Salamander`/`AgentDb`/`JsonDb`.
86#[doc(hidden)]
87pub use facade::{
88 AppendBatch as EngineAppendBatch, AppendReceiptDto as EngineAppendReceipt, BranchDto,
89 CommittedBatch, DurabilityDto, Engine, EngineError, EngineOptions, ErrorCategory, EventData,
90 ExpectedRevisionDto, FeedFilter, FeedHandle, FeedPage, FeedRequest, InputType, PartitionScheme,
91 PartitionStatus, PayloadCodec, ProjectionCursor, ProjectionDescriptor, ProjectionFailure,
92 ProjectionRuntime, ProjectionScope, ProjectionStatus, QueryConsistency, QueryDefinition,
93 QueryHandle, QueryOperation, QueryResult, ReaderHandle, RecordDto, ReplayPage, ReplayRequest,
94 StaleReason, MAX_FACADE_BATCH_BYTES, MAX_FACADE_PAYLOAD_BYTES, MAX_REPLAY_PAGE_BYTES,
95 MAX_REPLAY_PAGE_EVENTS,
96};
97pub use format::{
98 BatchId, BincodeCodec, BranchId, CodecId, DatabaseId, EventId, EventType, FormatLimits,
99 FrameKind, JsonCodec, Metadata, OwnedStoredRecord, RecordEnvelopeV2, StoredRecord, StreamId,
100 StreamRevision, TypedCodec,
101};
102#[doc(hidden)]
103pub use log::partition_of;
104pub use log::{LogReader, RecordReader, ReplayEnd, ReplayPlan, StreamSelector, VerificationMode};
105pub use projection::{NamespaceScoped, Projection};
106pub use view::{Change, IndexKey, IndexedView, View};
107
108pub use agent::AgentDb;
109pub use db::Salamander;
110pub use json::{Json, JsonDb};
111pub use migration::{migrate_legacy_branches, migrate_v1, BranchMigrationReport, MigrationReport};
112// Snapshot descriptors are surfaced only through the engine facade
113// (snapshot management is not on the typed `Salamander` API — instant
114// recovery uses snapshots internally). Reachable for bindings, hidden from
115// the documented surface.
116#[doc(hidden)]
117pub use snapshot::{SnapshotInfo, SnapshotManifest, MAX_SNAPSHOT_STATE_BYTES};
118pub use stream::{
119 AppendReceipt, AppendRequest, Durability, ExpectedRevision, IdempotencyKey, NewEvent,
120 ReceiptDurability, StreamName,
121};