Lens
Snapshots and Sub Databases
In-memory snapshot handles and prefix namespaces, without an ACL boundary.
sub and sub_with_options prefix keys in the same underlying Lens. A prefix is a namespace, not a tenant security boundary. Snapshots capture a root index and Strand length in a process-local map. Select one through ReadOptions.snapshot; ordinary reads on a subdatabase still use the live root. Snapshot registrations are not persisted/reloaded automatically.
This example is checked against source signatures; it was not compiled or run during this documentation pass.
use lens::{Lens, LensConfig, SubOptions};
use std::sync::Arc;
use strand::{Strand, StrandConfig};
use tokio::sync::RwLock as AsyncRwLock;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let dir = tempfile::tempdir()?;
let strand = Strand::new(StrandConfig::new().with_storage(dir.path())).await?;
let lens = Lens::new(Arc::new(AsyncRwLock::new(strand)), LensConfig::default()).await?;
// A SubDatabase is a prefix-isolated view onto the same physical tree.
// Prefix namespacing shares the parent storage and authorization boundary.
let users = lens.sub_with_options("users", SubOptions::default());
users.put(b"alice", b"admin").await?;
users.put(b"bob", b"reader").await?;
// Snapshot the current tree root so future writes don't change what we observe.
let snapshot_id = lens.snapshot_with_name("post-onboarding".to_string()).await?;
// Mutate the live tree after snapshotting.
users.put(b"carol", b"writer").await?;
// Inspect the process-local snapshot record; this is not a snapshot read.
let snap = lens.get_snapshot(&snapshot_id).expect("snapshot exists");
println!(
"snapshot id={} entries={} strand_length={} valid_now={}",
snap.id,
snap.metadata.entries,
snap.strand_length,
snap.is_valid_at(snap.strand_length),
);
lens.delete_snapshot(&snapshot_id)?;
Ok(())
}