use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use edgestore::vector::distance::Metric;
use edgestore::vector::types::{Dtype, VectorRecord};
use edgestore::{EdgestoreConfig, EdgestoreError, Engine, VectorEngine};
use tempfile::TempDir;
fn main() {
pattern_flush_callback();
pattern_vector_count();
pattern_readonly_guard();
}
fn pattern_flush_callback() {
println!("=== Pattern 1: flush callback ===");
let dir = TempDir::new().unwrap();
let flush_count = Arc::new(AtomicU64::new(0));
let flush_count2 = flush_count.clone();
let mut engine = Engine::open(EdgestoreConfig::new(dir.path()))
.unwrap()
.with_on_segment_flushed(move |meta| {
let n = flush_count2.fetch_add(1, Ordering::Relaxed) + 1;
println!(
" [callback] flush #{}: segment {} ({} bytes compressed)",
n, meta.segment_id, meta.compressed_bytes,
);
});
for i in 0u32..5 {
engine
.put(b"events", format!("e{:04}", i).as_bytes(), b"payload")
.unwrap();
}
engine.flush_to_segments().unwrap(); engine.put(b"events", b"e0005", b"payload2").unwrap();
engine.flush_to_segments().unwrap();
println!(
" Total flushes observed by callback: {}",
flush_count.load(Ordering::Relaxed)
);
println!();
}
fn pattern_vector_count() {
println!("=== Pattern 2: vector_count ===");
let dir = TempDir::new().unwrap();
let mut engine = Engine::open(EdgestoreConfig::new(dir.path())).unwrap();
println!(
" Before inserts: vector_count = {:?}",
engine.vector_count(b"products")
);
let v: Vec<u8> = (0u32..4).flat_map(|_| 1.0f32.to_le_bytes()).collect();
engine
.vector_put(b"products", b"p1", 4, Dtype::F32, &v)
.unwrap();
engine
.vector_put(b"products", b"p2", 4, Dtype::F32, &v)
.unwrap();
engine
.vector_put(b"products", b"p3", 4, Dtype::F32, &v)
.unwrap();
println!(
" After put, before search: vector_count = {:?}",
engine.vector_count(b"products")
);
engine.build_vector_index(b"products").unwrap();
println!(
" After build_vector_index: vector_count = {:?}",
engine.vector_count(b"products")
);
println!(" (None = index not loaded; Some(n) = HNSW node count)");
let query = VectorRecord {
dims: 4,
dtype: Dtype::F32,
data: v,
};
engine
.vector_search(b"products", &query, 2, Metric::Cosine)
.unwrap();
println!();
}
fn pattern_readonly_guard() {
println!("=== Pattern 3: read-only guard ===");
let dir = TempDir::new().unwrap();
{
let mut primary = Engine::open(EdgestoreConfig::new(dir.path())).unwrap();
primary.put(b"catalog", b"item1", b"Widget A").unwrap();
primary.put(b"catalog", b"item2", b"Widget B").unwrap();
primary.flush_to_segments().unwrap();
println!(" Primary wrote 2 items and flushed.");
}
let mut replica = Engine::open_readonly(EdgestoreConfig::new(dir.path())).unwrap();
let val = replica.get(b"catalog", b"item1").unwrap();
println!(
" Replica reads item1: {:?}",
val.map(|v| String::from_utf8_lossy(&v).into_owned())
);
match replica.put(b"catalog", b"item3", b"rogue write") {
Err(EdgestoreError::ReadOnly) => println!(" replica.put → Err(ReadOnly) ✓"),
other => panic!("expected ReadOnly, got {:?}", other),
}
match replica.delete(b"catalog", b"item1") {
Err(EdgestoreError::ReadOnly) => println!(" replica.delete → Err(ReadOnly) ✓"),
other => panic!("expected ReadOnly, got {:?}", other),
}
let items = replica.range(b"catalog", b"", b"\xff").unwrap();
println!(" Replica range scan: {} items", items.len());
println!();
let _ = HashMap::<String, String>::new();
}