use std::{path::Path, time::Instant};
use kcode_k1_persons_store::{PersonId, Store, TxId};
use kcode_k1_txn_ordering::{GENESIS_PARENT, K1TxnOrdering};
use rusqlite::{Connection, params};
use tempfile::TempDir;
fn canonical_ordering(root: &Path, count: usize) -> (K1TxnOrdering, Vec<TxId>) {
let ordering = K1TxnOrdering::open(root).unwrap();
let mut parent = GENESIS_PARENT;
let mut ids = Vec::with_capacity(count);
for nonce in 0..count {
let mut bytes = Vec::with_capacity(136);
bytes.extend_from_slice(parent.as_bytes());
bytes.extend_from_slice(&(nonce as u64).to_le_bytes());
bytes.extend_from_slice(&[7; 32]);
bytes.push(b'p');
bytes.extend_from_slice(&[0; 19]);
bytes.extend_from_slice(&[0; 64]);
let id = TxId::for_transaction(&bytes);
ordering.submit_txn(&bytes).unwrap();
ids.push(id);
parent = id;
}
(ordering, ids)
}
fn person(id: TxId) -> PersonId {
PersonId::from_tx_id(id)
}
#[test]
fn ten_thousand_person_snapshot_opens_under_five_seconds() {
fn assert_send<T: Send>() {}
assert_send::<Store>();
let store_root = TempDir::new().unwrap();
let ordering_root = TempDir::new().unwrap();
let (ordering, ids) = canonical_ordering(ordering_root.path(), 10_001);
let (store, snapshot) = Store::open(store_root.path(), &ordering).unwrap();
assert!(snapshot.persons().is_empty());
drop(store);
let mut connection = Connection::open(store_root.path().join("persons.sqlite3")).unwrap();
let transaction = connection.transaction().unwrap();
{
let mut insert = transaction
.prepare("INSERT INTO persons(id, root, name) VALUES(?1, ?2, ?3)")
.unwrap();
for index in 0..10_000 {
let id = ids[index].as_bytes();
let root = if index < 5_000 { ids[0].as_bytes() } else { id };
let name = if index == 0 || index >= 5_000 {
Some(format!("Person {index}"))
} else {
None
};
insert.execute(params![&id[..], &root[..], name]).unwrap();
}
}
transaction
.execute(
"UPDATE meta SET checkpoint = ?1",
params![&ids[10_000].as_bytes()[..]],
)
.unwrap();
transaction.commit().unwrap();
drop(connection);
let started = Instant::now();
let (_, snapshot) = Store::open(store_root.path(), &ordering).unwrap();
assert!(started.elapsed().as_secs_f64() < 5.0);
assert_eq!(snapshot.persons().len(), 10_000);
assert_eq!(
snapshot
.persons()
.iter()
.filter(|stored| stored.root() == person(ids[0]))
.count(),
5_000
);
}