Strand Blobs
Blob Store
BlobStore implementation: BLAKE3 content-addressed chunks, dedup tracking, metadata strand, and chunk strand stored side-by-side.
Purpose
Chunked blob storage with deduplication, cache, writer/reader APIs, repair, metrics, and policy hooks.
This page follows the real source shape for Strand Blobs and explains the workflow a developer is likely to use first.
Storage contract
Document persistence format, integrity checks, read/write ordering, idempotency, compaction or repair behavior, and how callers recover from partial failures. This section should answer what data is durable and what can be reconstructed.
Primary types to know
AllowAllBlobPolicy— models/strand-blobs/src/policy.rsBlobConfig— models/strand-blobs/src/config.rsBlobEntry— models/strand-blobs/src/chunk.rsBlobId— models/strand-blobs/src/blob.rsBlobInfo— models/strand-blobs/src/blob.rsBlobMetadata— models/strand-blobs/src/blob.rsBlobMetrics— models/strand-blobs/src/metrics.rsBlobMetricsSnapshot— models/strand-blobs/src/metrics.rsBlobReader— models/strand-blobs/src/reader.rsBlobStore— models/strand-blobs/src/store.rsBlobWriter— models/strand-blobs/src/writer.rsChunkCache— models/strand-blobs/src/cache.rs
Example shape
use strand::{Strand, StrandConfig};
use strand_blobs::{BlobConfig, BlobStore, ListOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// BlobStore is built from two strands: one for metadata, one for chunked data.
// It deduplicates by BLAKE3 chunk hash and tracks usage in dedup_stats().
let dir = tempfile::tempdir()?;
let meta = Strand::new(StrandConfig::new().with_storage(dir.path().join("meta"))).await?;
let data = Strand::new(StrandConfig::new().with_storage(dir.path().join("data"))).await?;
let store = BlobStore::new(meta, data, BlobConfig::default()).await?;
// put() ingests bytes and returns a BLAKE3-derived BlobId.
let id = store.put(b"a binary blob, content-addressed by BLAKE3".as_ref(), None).await?;
let _reader = store.get(&id).await?.expect("blob present");
// list() paginates blobs; the response carries an optional continuation cursor.
let listing = store.list(ListOptions::default()).await?;
let dedup = store.dedup_stats().await?;
println!(
"blobs_listed={} dedup_unique_chunks={} dedup_logical={}",
listing.items.len(),
dedup.unique_chunks,
dedup.logical_chunks,
);
Ok(())
}