use postcard::from_bytes;
use reifydb_catalog::CatalogStore;
use reifydb_core::{interface::catalog::flow::FlowId, internal};
use reifydb_transaction::transaction::Transaction;
use reifydb_value::error::Error;
use crate::{
Result,
flow::{
flow::FlowDag,
operator::{FlowEdge, FlowNode, OperatorDef},
},
};
pub fn load_flow_dag(txn: &mut Transaction<'_>, flow_id: FlowId) -> Result<FlowDag> {
let flow_def = CatalogStore::get_flow(txn, flow_id)?;
let node_defs = CatalogStore::list_operators_by_flow(txn, flow_id)?;
let edge_defs = CatalogStore::list_flow_edges_by_flow(txn, flow_id)?;
let mut builder = FlowDag::builder(flow_id);
for node_def in node_defs {
let node_type: OperatorDef = from_bytes(node_def.data.as_ref())
.map_err(|e| Error(Box::new(internal!("Failed to deserialize OperatorDef: {}", e))))?;
let node = FlowNode::new(node_def.id, node_type);
builder.add_node(node);
}
for edge_def in edge_defs {
let edge = FlowEdge::new(edge_def.id, edge_def.source, edge_def.target);
builder.add_edge(edge)?;
}
let flow = builder.build();
Ok(flow)
}
#[cfg(test)]
mod tests {
use postcard::to_allocvec;
use reifydb_catalog::test_utils::{create_flow, create_namespace, create_operator};
use reifydb_test_harness::engine::create_test_admin_transaction;
use super::*;
#[test]
fn the_loader_restores_every_persisted_operator() {
let mut txn = create_test_admin_transaction();
create_namespace(&mut txn, "test");
let flow = create_flow(&mut txn, "test", "win");
let encoded = to_allocvec(&OperatorDef::SourceInlineData {}).expect("encode");
let first = create_operator(&mut txn, flow.id, 0, &encoded);
let second = create_operator(&mut txn, flow.id, 0, &encoded);
let dag = load_flow_dag(&mut Transaction::Admin(&mut txn), flow.id).unwrap();
let mut restored: Vec<_> = dag.get_operator_ids().collect();
restored.sort();
let mut expected = vec![first.id, second.id];
expected.sort();
assert_eq!(restored, expected, "every persisted operator must come back");
assert_eq!(dag.id, flow.id, "the loaded graph keeps the flow identity it was asked for");
}
#[test]
fn a_flow_with_no_operators_loads_as_an_empty_graph() {
let mut txn = create_test_admin_transaction();
create_namespace(&mut txn, "test");
let flow = create_flow(&mut txn, "test", "empty");
let dag = load_flow_dag(&mut Transaction::Admin(&mut txn), flow.id).unwrap();
assert_eq!(dag.get_operator_ids().count(), 0, "no operators persisted, so none restored");
assert!(dag.topological_order().is_empty());
}
}