WeaveDocs
Lens

Batching

Batched writes in Lens — atomic multi-key commits, batch ordering, and per-batch durability guarantees.

Purpose

B-tree key/value database with batches, snapshots, sub-databases, iterators, cache, compaction, and metrics.

This page follows the real source shape for Lens and explains the workflow a developer is likely to use first.

Developer workflow

Start from the smallest constructor or builder, perform one meaningful operation, inspect the returned state, then add the relevant policy, storage, or network integration. The examples below should be expanded whenever the crate API changes.

Tip

Prefer one large Batch::commit over many single put calls for related writes — a batch is the only way to get atomicity across multiple keys.

Primary types to know

  • AllowAllLensPolicy — models/lens/src/lens_policy.rs
  • Batch — models/lens/src/batch.rs
  • BlockCache — models/lens/src/block.rs
  • BlockPointer — models/lens/src/node.rs
  • CacheStats — models/lens/src/block.rs
  • CompactionOptions — models/lens/src/config.rs
  • Key — models/lens/src/node.rs
  • Lens — models/lens/src/lens.rs
  • LensConfig — models/lens/src/config.rs
  • LensMetrics — models/lens/src/metrics.rs
  • LensMetricsSnapshot — models/lens/src/metrics.rs
  • Metadata — models/lens/src/lens.rs

Example shape

use lens::{Batch, BatchOp, Lens, LensConfig};
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>> {
    // Lens sits on top of a Strand. The order field controls B-tree fan-out.
    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?;

    // Build a Batch with several puts and one delete; the order is preserved
    // but `deduplicated()` returns at most one op per key for replay/diff use.
    let mut batch = Batch::new();
    batch.put("theme", "dark");
    batch.put("locale", "en-US");
    batch.put("font", "mono");
    batch.delete("theme"); // overrides the previous put for "theme"
    batch.validate(1024)?;

    let dedup_count = batch.deduplicated().len();
    lens.batch(&batch).await?;

    // Inspect what the batch contained before commit — useful for replication logs.
    for op in batch.operations() {
        match op {
            BatchOp::Put(key, value) => {
                println!("put {:?} ({} bytes)", key.as_bytes(), value.data.len())
            }
            BatchOp::Delete(key) => println!("del {:?}", key.as_bytes()),
        }
    }
    println!("batch_ops={} unique_keys={}", batch.len(), dedup_count);
    Ok(())
}