use crate::codec::frame_value;
use crate::dict::Dicts;
use crate::error::{storage_err, TopoError};
use crate::ids::{EdgeId, NodeId, Scope};
use crate::props::Props;
use crate::state::{EdgeRecord, NodeRecord};
use redb::{ReadableTable, Table};
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct NodeRecordV1 {
pub id: NodeId,
pub scope: Scope,
pub label: SmolStr,
pub props: Props,
pub embedding: Option<(String, Vec<f32>)>,
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct EdgeRecordV1 {
pub id: EdgeId,
pub scope: Scope,
pub ty: SmolStr,
pub from: NodeId,
pub to: NodeId,
pub props: Props,
pub valid_from: i64,
pub valid_to: Option<i64>,
}
pub(crate) fn migrate_v1_to_v2(
nodes: &mut Table<'_, &'static [u8], &'static [u8]>,
edges: &mut Table<'_, &'static [u8], &'static [u8]>,
embeddings: &mut Table<'_, &'static [u8], &'static [u8]>,
dict_table: &mut Table<'_, &'static [u8], &'static str>,
dicts: &mut Dicts,
) -> Result<(), TopoError> {
let vals = nodes
.iter()
.map_err(storage_err)?
.map(|x| x.map(|(_, v)| v.value().to_vec()))
.collect::<Result<Vec<_>, _>>()
.map_err(storage_err)?;
for b in vals {
let old: NodeRecordV1 =
postcard::from_bytes(&b).map_err(|e| TopoError::Encoding(e.to_string()))?;
if let Some((m, v)) = &old.embedding {
let raw =
postcard::to_allocvec(&(m, v)).map_err(|e| TopoError::Encoding(e.to_string()))?;
let framed = frame_value(raw);
embeddings
.insert(
crate::storage::node_key(old.id).as_slice(),
framed.as_slice(),
)
.map_err(storage_err)?;
}
let n = NodeRecord {
id: old.id,
scope: old.scope,
label: old.label,
props: old.props,
embedding: None,
};
let raw = postcard::to_allocvec(&crate::disk::node_to_disk(&n, dict_table, dicts)?)
.map_err(|e| TopoError::Encoding(e.to_string()))?;
let f = frame_value(raw);
nodes
.insert(crate::storage::node_key(n.id).as_slice(), f.as_slice())
.map_err(storage_err)?;
}
let vals = edges
.iter()
.map_err(storage_err)?
.map(|x| x.map(|(_, v)| v.value().to_vec()))
.collect::<Result<Vec<_>, _>>()
.map_err(storage_err)?;
for b in vals {
let old: EdgeRecordV1 =
postcard::from_bytes(&b).map_err(|e| TopoError::Encoding(e.to_string()))?;
let e = EdgeRecord {
id: old.id,
scope: old.scope,
ty: old.ty,
from: old.from,
to: old.to,
props: old.props,
valid_from: old.valid_from,
valid_to: old.valid_to,
};
let raw = postcard::to_allocvec(&crate::disk::edge_to_disk(&e, dict_table, dicts)?)
.map_err(|e| TopoError::Encoding(e.to_string()))?;
let f = frame_value(raw);
edges
.insert(e.id.as_u128().to_be_bytes().as_slice(), f.as_slice())
.map_err(storage_err)?;
}
Ok(())
}