use verit::{
encode, Dt, FileView, FileWriter, Message, SchemaBuilder, SchemaMode, SchemaRegistry, Value,
Verit, VeritType,
};
#[derive(Verit, Debug, Clone, Copy, PartialEq)]
#[verit(mode = "dense")]
struct Coord {
#[verit(id = 1)]
lat: f64,
#[verit(id = 2)]
lon: f64,
}
#[derive(Verit, Debug, Clone, PartialEq)]
struct Event {
#[verit(id = 1)]
seq: u64,
#[verit(id = 2)]
kind: String,
#[verit(id = 3)]
payload: String,
#[verit(id = 4)]
at: Option<Coord>,
#[verit(id = 5)]
tags: Vec<String>,
#[verit(id = 6)]
region: Option<String>,
}
fn event(seq: u64, kind: &str, payload: &str, tags: &[&str]) -> Event {
Event {
seq,
kind: kind.into(),
payload: payload.into(),
at: None,
tags: tags.iter().map(|t| t.to_string()).collect(),
region: None,
}
}
fn main() {
println!("== Veritate event store — reference integration ==\n");
let path =
std::env::temp_dir().join(format!("veritate-eventstore-{}.verit", std::process::id()));
let _ = std::fs::remove_file(&path);
let first = Event {
seq: 1,
kind: "login".into(),
payload: "user=alice".into(),
at: Some(Coord {
lat: 51.5,
lon: -0.12,
}),
tags: vec!["auth".into()],
region: Some("eu-west".into()),
};
let second = event(2, "purchase", "sku=42 qty=3", &["billing", "priority"]);
let mut store = FileWriter::create(&path).unwrap();
let schema = Event::verit_schema();
let id_first = store
.append_message(schema, &first.to_verit(SchemaMode::HashOnly).unwrap())
.unwrap();
let id_second = store
.append_message(schema, &second.to_verit(SchemaMode::HashOnly).unwrap())
.unwrap();
store.commit().unwrap();
let after_first_commit = std::fs::metadata(&path).unwrap().len();
println!(
"producer: appended 2 events → ids {id_first}, {id_second}; \
{after_first_commit}-byte .verit file at generation {}",
store.generation()
);
let image = std::fs::read(&path).unwrap();
{
let log = FileView::open(&image).unwrap();
println!(
"consumer: opened the file cold — {} records, generation {}, {} schema(s) inside it",
log.len(),
log.generation(),
log.schemas().len()
);
for (i, original) in [&first, &second].iter().enumerate() {
let back = Event::from_verit(log.get(i).unwrap()).unwrap();
println!(
" [id {}] seq={} kind={} tags={:?}",
log.record(i).unwrap().id,
back.seq,
back.kind,
back.tags
);
assert_eq!(&back, *original, "record {i} round-trips");
}
println!(" dump_json(0) = {}", log.dump_json(0).unwrap());
}
println!();
let checkpoint = id_second;
println!("consumer: processed through record id {checkpoint}; checkpointing there");
let third = event(3, "logout", "user=alice", &["auth"]);
let id_third = store
.append_message(schema, &third.to_verit(SchemaMode::HashOnly).unwrap())
.unwrap();
let legacy_schema = SchemaBuilder::new()
.add_struct(
"Event",
vec![
(1, "seq", Dt::U32), (2, "kind", Dt::Str),
(3, "payload", Dt::Str),
],
)
.build("Event")
.unwrap();
let legacy_bytes = encode(
&legacy_schema,
&Value::Struct(vec![
(1, Value::U32(99)),
(2, Value::str("healthcheck")),
(3, Value::str("ok")),
]),
SchemaMode::HashOnly,
)
.unwrap();
let id_legacy = store.append_message(&legacy_schema, &legacy_bytes).unwrap();
store.commit().unwrap();
println!(
"producer: appended 2 more (ids {id_third}, {id_legacy}) — generation {}",
store.generation()
);
let image = std::fs::read(&path).unwrap();
{
let log = FileView::open(&image).unwrap();
let fresh: Vec<u64> = log.records_after(checkpoint).map(|r| r.id).collect();
println!("consumer: records_after({checkpoint}) → ids {fresh:?}");
assert_eq!(fresh, vec![id_third, id_legacy]);
assert_eq!(
log.schemas().len(),
2,
"the file now carries both schema versions"
);
let at = log.find_by_id(id_legacy).unwrap();
let resolver = log.resolver_for(at, Event::verit_schema()).unwrap();
let root = log.message(at).unwrap().root(&resolver).unwrap();
println!(
"consumer: read the v1 record through today's schema: seq={:?} kind={:?} at={:?}",
root.get_u64(1).unwrap(),
root.get_str(2).unwrap(),
root.get_struct(4).unwrap().map(|_| "present"),
);
assert_eq!(root.get_u64(1).unwrap(), Some(99), "u32 seq widened to u64");
assert_eq!(root.get_str(2).unwrap(), Some("healthcheck"));
assert!(
root.get_struct(4).unwrap().is_none(),
"`at` did not exist in v1 data"
);
}
println!();
let torn = &image[..(after_first_commit as usize + 16).min(image.len() - 1)];
{
let rolled_back = FileView::open(torn).unwrap();
println!(
"crash sim: truncated mid-commit → opened at generation {} with {} records \
(the torn commit never happened)",
rolled_back.generation(),
rolled_back.len()
);
assert_eq!(rolled_back.len(), 2, "rolled back to the 2-record state");
assert_eq!(rolled_back.generation(), 2);
}
println!();
let pii = event(4, "profile", "email=alice@example.com", &["pii"]);
let id_pii = store
.append_message(schema, &pii.to_verit(SchemaMode::HashOnly).unwrap())
.unwrap();
store.commit().unwrap();
store.remove_id(id_pii).unwrap();
store.commit().unwrap();
let image = std::fs::read(&path).unwrap();
let still_there = image
.windows(b"alice@example.com".len())
.any(|w| w == b"alice@example.com");
println!(
"retention: removed id {id_pii} — unlinked from the index, \
but the bytes are still in the file: {still_there}"
);
assert!(still_there, "removal must not erase — spec §8.2");
store.purge_ids(&[id_pii]).unwrap();
let image = std::fs::read(&path).unwrap();
let gone = !image
.windows(b"alice@example.com".len())
.any(|w| w == b"alice@example.com");
println!("retention: purge_ids → compacted, bytes erased: {gone}");
assert!(gone, "purge_ids must erase");
{
let log = FileView::open(&image).unwrap();
let fresh: Vec<u64> = log.records_after(checkpoint).map(|r| r.id).collect();
println!(
"consumer: after compaction, records_after({checkpoint}) → ids {fresh:?} \
(generation reset to {})",
log.generation()
);
assert_eq!(fresh, vec![id_third, id_legacy], "ids survived compaction");
assert_eq!(log.generation(), 1, "compaction rebuilds at generation 1");
assert!(
log.next_record_id() > id_pii,
"a purged record's id is retired, never reissued"
);
}
println!();
let mut producer_registry = SchemaRegistry::new();
producer_registry.register(Event::verit_schema().clone());
let bundle = producer_registry.to_bundle();
let consumer_registry = SchemaRegistry::from_bundle(&bundle).unwrap();
let on_the_wire = second.to_verit(SchemaMode::HashOnly).unwrap();
let msg = Message::parse(&on_the_wire).unwrap();
let resolver = consumer_registry
.resolver_for(msg.schema_id(), Event::verit_schema())
.unwrap();
let root = msg.root(&resolver).unwrap();
println!(
"wire: a peer's hash-only message resolved via a {}-byte distribution bundle: kind={:?}",
bundle.len(),
root.get_str(2).unwrap()
);
assert_eq!(root.get_str(2).unwrap(), Some("purchase"));
let _ = std::fs::remove_file(&path);
println!("\n== every round-trip, the evolution read, the rollback, and the erasure passed ==");
}