use fathomdb_embedder_api::{Embedder, EmbedderError, EmbedderIdentity, Vector};
use fathomdb_engine::{Engine, InitialState, PreparedWrite, SourceId};
use fathomdb_schema::SQLITE_SUFFIX;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use tempfile::TempDir;
const ROWS: usize = 200;
const MAX_ATTEMPTS: usize = 8;
#[derive(Debug)]
struct CountingDelayEmbedder {
identity: EmbedderIdentity,
calls: Arc<AtomicUsize>,
texts: Arc<Mutex<HashMap<String, usize>>>,
}
impl CountingDelayEmbedder {
fn new(calls: Arc<AtomicUsize>, texts: Arc<Mutex<HashMap<String, usize>>>) -> Self {
Self { identity: EmbedderIdentity::new("deterministic", "rev-a", 384), calls, texts }
}
}
impl Embedder for CountingDelayEmbedder {
fn identity(&self) -> EmbedderIdentity {
self.identity.clone()
}
fn embed(&self, text: &str) -> Result<Vector, EmbedderError> {
self.calls.fetch_add(1, Ordering::SeqCst);
*self
.texts
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner())
.entry(text.to_string())
.or_insert(0) += 1;
std::thread::sleep(Duration::from_millis(1));
let mut v = vec![0.0_f32; self.identity.dimension as usize];
v[0] = 1.0;
Ok(v)
}
}
fn node(i: usize, governed: bool) -> PreparedWrite {
PreparedWrite::Node {
kind: "doc".to_string(),
body: format!(r#"{{"summary":"meaning {i}"}}"#),
source_id: SourceId::new("test:fixture").expect("source id"),
logical_id: if governed { Some(format!("tc57-wp-{i}")) } else { None },
state: InitialState::Active,
reason: None,
valid_from: None,
valid_until: None,
}
}
fn ro(path: &Path) -> rusqlite::Connection {
rusqlite::Connection::open_with_flags(
path,
rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY | rusqlite::OpenFlags::SQLITE_OPEN_URI,
)
.expect("open read-only")
}
fn db_path(dir: &TempDir, name: &str) -> PathBuf {
dir.path().join(format!("{name}{SQLITE_SUFFIX}"))
}
fn count(conn: &rusqlite::Connection, sql: &str) -> i64 {
conn.query_row(sql, [], |r| r.get::<_, i64>(0)).unwrap_or(-1)
}
struct LoadOutcome {
label: &'static str,
rows_written: usize,
rows_lost: usize,
caller_errors: usize,
ok_write_wall_ms: u128,
total_wall_ms: u128,
embed_calls: usize,
repeated_texts: usize,
repeat_embeds: usize,
drain_ok: bool,
drain_ms: u128,
failure_audit_rows: i64,
failed_terminals: i64,
vector_rows: i64,
}
impl LoadOutcome {
fn report(&self) {
println!(
"TC57-PARTC arm={} rows_written={} rows_lost={} caller_errors={} \
embed_calls={} repeated_texts={} repeat_embeds={} failed_terminals={} \
failure_audit_rows={} vector_rows={} drain_ok={} drain_ms={} \
ok_write_wall_ms={} total_wall_ms={}",
self.label,
self.rows_written,
self.rows_lost,
self.caller_errors,
self.embed_calls,
self.repeated_texts,
self.repeat_embeds,
self.failed_terminals,
self.failure_audit_rows,
self.vector_rows,
self.drain_ok,
self.drain_ms,
self.ok_write_wall_ms,
self.total_wall_ms,
);
}
}
fn run_load(label: &'static str, governed: bool) -> LoadOutcome {
let dir = TempDir::new().expect("tempdir");
let path = db_path(&dir, if governed { "tc57_wp_governed" } else { "tc57_wp_anonymous" });
let calls = Arc::new(AtomicUsize::new(0));
let texts: Arc<Mutex<HashMap<String, usize>>> = Arc::new(Mutex::new(HashMap::new()));
let opened = Engine::open_with_embedder_for_test(
&path,
Arc::new(CountingDelayEmbedder::new(calls.clone(), texts.clone())),
)
.expect("open");
let engine = &opened.engine;
engine.configure_vector_kind_for_test("doc").expect("vector kind");
let mut rows_written = 0_usize;
let mut rows_lost = 0_usize;
let mut caller_errors = 0_usize;
let mut ok_write_wall_ms = 0_u128;
let loop_started = Instant::now();
for i in 0..ROWS {
let mut landed = false;
for _ in 0..MAX_ATTEMPTS {
let started = Instant::now();
let result = engine.write(&[node(i, governed)]);
let elapsed = started.elapsed().as_millis();
match result {
Ok(_) => {
ok_write_wall_ms += elapsed;
rows_written += 1;
landed = true;
break;
}
Err(_) => {
caller_errors += 1;
std::thread::sleep(Duration::from_millis(5));
}
}
}
if !landed {
rows_lost += 1;
}
std::thread::sleep(Duration::from_millis(1));
}
let total_wall_ms = loop_started.elapsed().as_millis();
let drain_started = Instant::now();
let drain_ok = engine.drain(60_000).is_ok();
let drain_ms = drain_started.elapsed().as_millis();
let embed_calls = calls.load(Ordering::SeqCst);
let (repeated_texts, repeat_embeds) = {
let seen = texts.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
let repeated = seen.values().filter(|n| **n > 1).count();
let extra: usize = seen.values().map(|n| n.saturating_sub(1)).sum();
(repeated, extra)
};
opened.engine.close().expect("close");
let conn = ro(&path);
let outcome = LoadOutcome {
label,
rows_written,
rows_lost,
caller_errors,
ok_write_wall_ms,
total_wall_ms,
embed_calls,
repeated_texts,
repeat_embeds,
drain_ok,
drain_ms,
failure_audit_rows: count(
&conn,
"SELECT COUNT(*) FROM operational_mutations
WHERE collection_name = 'projection_failures'",
),
failed_terminals: count(
&conn,
"SELECT COUNT(*) FROM _fathomdb_projection_terminal WHERE state = 'failed'",
),
vector_rows: count(&conn, "SELECT COUNT(*) FROM _fathomdb_vector_rows"),
};
outcome.report();
outcome
}
#[test]
fn tc57_worker_side_commit_pressure_governed() {
let outcome = run_load("governed", true);
assert!(
outcome.embed_calls > 0 && outcome.vector_rows > 0,
"non-vacuity: the worker must have embedded and committed real rows, else this \
measurement says nothing about worker-side commit pressure"
);
assert_eq!(outcome.rows_lost, 0, "every row must land within {MAX_ATTEMPTS} attempts");
assert_eq!(
outcome.failed_terminals, 0,
"the fix must not convert a caller-side write race into worker-side `failed` terminals"
);
assert_eq!(outcome.failure_audit_rows, 0, "nor into `projection_failures` audit rows");
assert!(outcome.drain_ok, "drain must still reach idle");
assert_eq!(
outcome.repeat_embeds, 0,
"worker outcomes must not be dropped and re-embedded ({} repeats over {} rows, {} texts repeated)",
outcome.repeat_embeds, outcome.rows_written, outcome.repeated_texts
);
}
#[test]
fn tc57_worker_side_commit_pressure_anonymous() {
let outcome = run_load("anonymous", false);
assert!(
outcome.embed_calls > 0 && outcome.vector_rows > 0,
"non-vacuity: the worker must have embedded and committed real rows"
);
assert_eq!(outcome.rows_lost, 0, "every row must land within {MAX_ATTEMPTS} attempts");
assert_eq!(
outcome.caller_errors, 0,
"the anonymous pressure arm must not produce caller write errors"
);
assert_eq!(outcome.failed_terminals, 0, "no worker-side `failed` terminals");
assert_eq!(outcome.failure_audit_rows, 0, "no `projection_failures` audit rows");
assert!(outcome.drain_ok, "drain must still reach idle");
assert_eq!(outcome.repeat_embeds, 0, "anonymous worker outcomes must not be re-embedded");
}