kmp-adapter-embedded 0.18.4

Embedded SQLite storage adapters for every KMP persistence port
Documentation
use std::fs;
use std::time::SystemTime;

use kmp_adapter_embedded::{EmbeddedKernelStore, StorageEngine};
use kmp_domain::{ContextEventStore, ContextUpdatedEvent};

fn event(revision: u64) -> ContextUpdatedEvent {
    ContextUpdatedEvent {
        root_node_id: "test:sqlite-lifecycle".to_string(),
        role: "memory".to_string(),
        revision,
        content_hash: format!("hash-{revision}"),
        changes: Vec::new(),
        idempotency_key: None,
        logical_digest: None,
        requested_by: None,
        occurred_at: SystemTime::now(),
    }
}

#[tokio::test]
async fn pinned_reader_keeps_committed_snapshot_while_writer_advances() {
    let data_dir = tempfile::tempdir().expect("data dir");
    let store = EmbeddedKernelStore::open_with_engine(data_dir.path(), StorageEngine::Sqlite)
        .expect("store opens");
    store.append(event(1), 0).await.expect("first commit");

    let snapshot = store.read_snapshot().await.expect("snapshot opens");
    store.append(event(2), 1).await.expect("second commit");

    assert_eq!(
        snapshot.event_log_stats().await.expect("pinned log stats"),
        (1, 1),
        "reader retains the snapshot from before the writer commit"
    );
    assert_eq!(
        store.event_log_stats().await.expect("current log stats"),
        (2, 2),
        "the current writer sees its committed event"
    );
}

#[test]
fn corrupt_kernel_input_is_refused_before_use() {
    let data_dir = tempfile::tempdir().expect("data dir");
    fs::create_dir_all(data_dir.path().join("store")).expect("store directory");
    fs::write(
        data_dir.path().join("FORMAT_VERSION"),
        format!("{}\n", StorageEngine::Sqlite.format_version()),
    )
    .expect("format stamp");
    fs::write(data_dir.path().join("store/kernel.sqlite3"), b"not sqlite").expect("corrupt kernel");

    let error = EmbeddedKernelStore::open(data_dir.path())
        .expect_err("corrupt SQLite input must be refused");
    assert!(
        error.to_string().contains("embedded store") || error.to_string().contains("SQLite"),
        "error identifies the rejected SQLite input: {error}"
    );
}