Skip to main content

kmp_adapter_embedded/adapter/
snapshot_store.rs

1use kmp_domain::{KmpBundle, PortError, SnapshotSaveOptions, SnapshotStore};
2
3use super::engine::{Key, Table};
4use super::store::EmbeddedKernelStore;
5
6impl SnapshotStore for EmbeddedKernelStore {
7    async fn save_bundle_with_options(
8        &self,
9        bundle: &KmpBundle,
10        options: SnapshotSaveOptions,
11    ) -> Result<(), PortError> {
12        // The snapshot port is write-only; persist an auditable summary keyed
13        // by (root, role) so a stored decision context can be accounted for
14        // offline. Full bundle rendering stays above the ports.
15        let root_node_id = bundle.root_node().node_id().to_string();
16        let role = bundle.role().as_str().to_string();
17        let record = serde_json::json!({
18            "root_node_id": root_node_id,
19            "role": role,
20            "neighbor_node_ids": bundle
21                .neighbor_nodes()
22                .iter()
23                .map(|node| node.node_id())
24                .collect::<Vec<_>>(),
25            "relationship_count": bundle.relationships().len(),
26            "node_detail_count": bundle.node_details().len(),
27            "ttl_seconds": options.ttl_seconds(),
28        });
29        let bytes = serde_json::to_vec(&record).map_err(|error| {
30            PortError::InvalidState(format!(
31                "embedded store could not encode snapshot summary: {error}"
32            ))
33        })?;
34
35        self.run(move |store| {
36            let mut tx = store.begin_write()?;
37            tx.insert(Table::Snapshots, Key::Str2(&root_node_id, &role), &bytes)?;
38            tx.commit()
39        })
40        .await
41    }
42}