haematite-cli 0.21.10

The haematite command: serve a store, its door and Studio, answer MCP, query with jq, and host the store's assistant seat
Documentation
use std::time::Instant;

use serde_json::{Value, json};

use super::options::{Options, directory_bytes};
use super::served::Writer;
use super::{ProbeResult, Table};

const WORDS: [&str; 32] = [
    "troponin",
    "patient",
    "ward",
    "review",
    "blood",
    "pressure",
    "pulse",
    "oxygen",
    "chest",
    "pain",
    "stable",
    "monitor",
    "nurse",
    "doctor",
    "test",
    "result",
    "morning",
    "evening",
    "normal",
    "repeat",
    "care",
    "plan",
    "heart",
    "rhythm",
    "temperature",
    "fluid",
    "oral",
    "dose",
    "follow",
    "observe",
    "sample",
    "rest",
];
const STATUSES: [&str; 3] = ["open", "closed", "pending"];
pub const TEXT_SEED: u64 = 0x4841_454d_5445_5854;
pub const VECTOR_SEED: u64 = 0x4841_454d_5645_4354;

pub fn note_id(index: u32) -> String {
    format!("n{index:010}")
}

fn patient_id(index: u32) -> String {
    format!("p{index:010}")
}

fn ward_id(index: u32) -> String {
    format!("w{index:02}")
}

pub fn build(
    writer: &mut Writer,
    options: &Options,
    directory: &std::path::Path,
    table: &mut Table,
) -> ProbeResult<()> {
    collections(writer, table)?;
    documents(writer, options, table)?;
    relations(writer, options.records, table)?;
    vectors(writer, options, table)?;
    let started = Instant::now();
    let bytes = directory_bytes(&directory.join("database"))?;
    let elapsed = started.elapsed();
    table.size(
        "store logical file bytes after build",
        elapsed,
        bytes.logical,
        "Rust metadata walk; file lengths; hard links counted once; excludes config and socket",
    )?;
    table.size(
        "store allocated bytes after build",
        elapsed,
        bytes.allocated,
        "same Rust walk; Unix 512-byte blocks including directories; hard links counted once",
    )?;
    table.metadata("query head", &serde_json::to_string(&writer.head)?)?;
    Ok(())
}

fn collections(writer: &mut Writer, table: &mut Table) -> ProbeResult<()> {
    let started = Instant::now();
    for collection in ["patients", "notes", "wards"] {
        writer.apply(
            "collection.put",
            &json!({"collection": collection, "schema": null}),
        )?;
    }
    table.measured(
        "collections declared",
        started.elapsed(),
        3,
        "collection.put; durable replies",
    )?;
    Ok(())
}

fn documents(writer: &mut Writer, options: &Options, table: &mut Table) -> ProbeResult<()> {
    let patients = options.records / 10;
    let started = Instant::now();
    put_batches(writer, "wards", 20, |index| {
        Ok(json!({"id": ward_id(index)}))
    })?;
    put_batches(writer, "patients", patients, |index| {
        Ok(json!({"id": patient_id(index), "ward": ward_id(index % 20)}))
    })?;
    table.measured(
        "patients and wards written",
        started.elapsed(),
        patients + 20,
        "documents.put_many; batches of at most 1000",
    )?;
    let mut text = Generator::new(TEXT_SEED);
    let mut hits = 0_u32;
    let started = Instant::now();
    put_batches(writer, "notes", options.records, |index| {
        let body = text.body(index)?;
        if body.split_whitespace().any(|word| word == "troponin") {
            hits = hits
                .checked_add(1)
                .ok_or("troponin hit count exceeds u32")?;
        }
        let patient = index % patients;
        let status = STATUSES
            .get(usize::try_from(index % 3)?)
            .ok_or("status index is outside the fixture vocabulary")?;
        Ok(json!({
            "id": note_id(index), "patient_id": patient_id(patient),
            "patient": {"id": patient_id(patient)}, "ward": ward_id(patient % 20),
            "status": status, "body": body, "written": index
        }))
    })?;
    table.measured(
        "notes written",
        started.elapsed(),
        options.records,
        "documents.put_many; batches of at most 1000; includes generation and encoding",
    )?;
    table.metadata("fixture troponin hits", &hits.to_string())?;
    Ok(())
}

fn relations(writer: &mut Writer, records: u32, table: &mut Table) -> ProbeResult<()> {
    let patients = records / 10;
    let started = Instant::now();
    for (relation, from, to) in [("about", "notes", "patients"), ("in", "patients", "wards")] {
        writer.apply(
            "relation.put",
            &json!({"relation": relation, "from_collection": from,
            "to_collection": to, "cardinality": "many_to_many"}),
        )?;
    }
    table.measured(
        "relations declared",
        started.elapsed(),
        2,
        "relation.put declares kinds; edge.put writes each member",
    )?;
    let started = Instant::now();
    for index in 0..records {
        edge(
            writer,
            "about",
            "notes",
            &note_id(index),
            "patients",
            &patient_id(index % patients),
        )?;
    }
    for index in 0..patients {
        edge(
            writer,
            "in",
            "patients",
            &patient_id(index),
            "wards",
            &ward_id(index % 20),
        )?;
    }
    let relations = records
        .checked_add(patients)
        .ok_or("relation count exceeds u32")?;
    table.measured(
        "relations written",
        started.elapsed(),
        relations,
        "edge.put; one durable mutation per edge",
    )?;
    Ok(())
}

fn vectors(writer: &mut Writer, options: &Options, table: &mut Table) -> ProbeResult<()> {
    let mut vectors = Generator::new(VECTOR_SEED);
    let started = Instant::now();
    for index in 0..options.records {
        writer.apply(
            "vector.put",
            &json!({"collection": "notes", "document_id": note_id(index),
            "field": "body_vec", "vector": vectors.unit_vector(options.dims)?}),
        )?;
    }
    table.measured(
        "vectors written",
        started.elapsed(),
        options.records,
        "vector.put; seeded unit vectors; includes generation and encoding",
    )?;
    table.metadata("vector declaration", &format!(
        "notes.body_vec: supplied, {} dimensions, fixed by first vector.put; vector.declare is embedded-only",
        options.dims))?;
    Ok(())
}

fn put_batches(
    writer: &mut Writer,
    collection: &str,
    count: u32,
    mut document: impl FnMut(u32) -> ProbeResult<Value>,
) -> ProbeResult<()> {
    let mut start = 0_u32;
    while start < count {
        let end = start.saturating_add(1000).min(count);
        let mut documents = Vec::new();
        for index in start..end {
            let id = match collection {
                "notes" => note_id(index),
                "patients" => patient_id(index),
                "wards" => ward_id(index),
                _ => return Err("unknown fixture collection".into()),
            };
            documents.push(json!({"document_id": id, "document": document(index)?}));
        }
        writer.apply(
            "documents.put_many",
            &json!({"collection": collection, "documents": documents}),
        )?;
        start = end;
    }
    Ok(())
}

fn edge(
    writer: &mut Writer,
    relation: &str,
    from_collection: &str,
    from: &str,
    to_collection: &str,
    to: &str,
) -> ProbeResult<()> {
    writer.apply(
        "edge.put",
        &json!({"relation": relation,
        "from": {"collection": from_collection, "document_id": from},
        "to": {"collection": to_collection, "document_id": to}, "properties": {}}),
    )
}

struct Generator {
    state: u64,
}

impl Generator {
    const fn new(state: u64) -> Self {
        Self { state }
    }

    const fn next(&mut self) -> u64 {
        self.state = self.state.wrapping_add(0x9e37_79b9_7f4a_7c15);
        let mut value = self.state;
        value = (value ^ (value >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
        value = (value ^ (value >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
        value ^ (value >> 31)
    }

    fn below(&mut self, bound: usize) -> ProbeResult<usize> {
        if bound == 0 {
            return Err("generator bound must be positive".into());
        }
        Ok(usize::try_from(self.next() % u64::try_from(bound)?)?)
    }

    fn body(&mut self, index: u32) -> ProbeResult<String> {
        let count = 20 + self.below(41)?;
        let mut words = Vec::with_capacity(count);
        for position in 0..count {
            let word = if position == 0 && index.is_multiple_of(10) {
                "troponin"
            } else {
                WORDS
                    .get(self.below(WORDS.len())?)
                    .copied()
                    .ok_or("word index is outside the fixture vocabulary")?
            };
            words.push(word);
        }
        Ok(words.join(" "))
    }

    fn unit_vector(&mut self, dims: usize) -> ProbeResult<Vec<f32>> {
        let mut vector = Vec::new();
        vector.try_reserve_exact(dims)?;
        for _ in 0..dims {
            let bits = u16::try_from(self.next() >> 48)?;
            vector.push(f32::from(bits) / 32_767.5 - 1.0);
        }
        let norm = vector
            .iter()
            .map(|value| f64::from(*value).powi(2))
            .sum::<f64>()
            .sqrt();
        if !norm.is_finite() || norm <= 0.0 {
            return Err("seeded vector has no finite positive norm".into());
        }
        for value in &mut vector {
            *value = num_traits::ToPrimitive::to_f32(&(f64::from(*value) / norm))
                .ok_or("normalized component is not representable as f32")?;
        }
        Ok(vector)
    }
}