Skip to main content

kmp_adapter_embedded/adapter/
node_detail.rs

1use kmp_domain::{NodeDetailProjection, NodeDetailReader, PortError};
2
3use super::engine::{Key, ReadTx, Table};
4use super::serdes::{DetailRecord, decode};
5use super::store::EmbeddedKernelStore;
6
7pub(super) fn read_batch(
8    tx: &dyn ReadTx,
9    node_ids: &[String],
10) -> Result<Vec<Option<NodeDetailProjection>>, PortError> {
11    node_ids
12        .iter()
13        .map(|id| {
14            tx.get(Table::Details, Key::Str(id))?
15                .map(|raw| decode::<DetailRecord>("node detail", &raw).map(Into::into))
16                .transpose()
17        })
18        .collect()
19}
20
21/// Stored record bytes for each id, in the requested order, duplicates and
22/// absent slots preserved exactly as `read_batch` reports them. Nothing is
23/// loaded or decoded: the answer counts the stored detail record, envelope
24/// included, which is larger than the canonical body inside it. It bounds what
25/// a later read would fetch from this table, not the memory a request holds.
26pub(super) fn size_batch(
27    tx: &dyn ReadTx,
28    node_ids: &[String],
29) -> Result<Vec<Option<u64>>, PortError> {
30    node_ids
31        .iter()
32        .map(|id| tx.value_len(Table::Details, Key::Str(id)))
33        .collect()
34}
35
36impl NodeDetailReader for EmbeddedKernelStore {
37    async fn load_node_detail(
38        &self,
39        node_id: &str,
40    ) -> Result<Option<NodeDetailProjection>, PortError> {
41        let node_id = node_id.to_string();
42        self.run(move |store| {
43            let tx = store.begin_read()?;
44            match tx.get(Table::Details, Key::Str(&node_id))? {
45                Some(raw) => Ok(Some(decode::<DetailRecord>("node detail", &raw)?.into())),
46                None => Ok(None),
47            }
48        })
49        .await
50    }
51
52    async fn load_node_details_batch(
53        &self,
54        node_ids: Vec<String>,
55    ) -> Result<Vec<Option<NodeDetailProjection>>, PortError> {
56        self.run(move |store| {
57            let tx = store.begin_read()?;
58            read_batch(tx.as_ref(), &node_ids)
59        })
60        .await
61    }
62}
63
64#[cfg(test)]
65#[path = "node_detail_size_tests.rs"]
66mod size_tests;