reifydb_catalog/store/flow_node/
delete.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use reifydb_core::{
5	interface::{CommandTransaction, FlowNodeId},
6	key::{FlowNodeByFlowKey, FlowNodeKey},
7};
8
9use crate::CatalogStore;
10
11impl CatalogStore {
12	pub async fn delete_flow_node(txn: &mut impl CommandTransaction, node_id: FlowNodeId) -> crate::Result<()> {
13		// First, get the node to find the flow ID for index deletion
14		let node = CatalogStore::find_flow_node(txn, node_id).await?;
15
16		if let Some(node_def) = node {
17			// Delete from main flow_node table
18			txn.remove(&FlowNodeKey::encoded(node_id)).await?;
19
20			// Delete from flow_node_by_flow index
21			txn.remove(&FlowNodeByFlowKey::encoded(node_def.flow, node_id)).await?;
22		}
23
24		Ok(())
25	}
26}
27
28#[cfg(test)]
29mod tests {
30	use reifydb_core::interface::FlowNodeId;
31	use reifydb_engine::test_utils::create_test_command_transaction;
32
33	use crate::{
34		CatalogStore,
35		test_utils::{create_flow_node, create_namespace, ensure_test_flow},
36	};
37
38	#[tokio::test]
39	async fn test_delete_flow_node() {
40		let mut txn = create_test_command_transaction().await;
41		let _namespace = create_namespace(&mut txn, "test_namespace").await;
42		let flow = ensure_test_flow(&mut txn).await;
43
44		let node = create_flow_node(&mut txn, flow.id, 1, &[0x01]).await;
45
46		// Node should exist
47		assert!(CatalogStore::find_flow_node(&mut txn, node.id).await.unwrap().is_some());
48
49		// Delete node
50		CatalogStore::delete_flow_node(&mut txn, node.id).await.unwrap();
51
52		// Node should no longer exist
53		assert!(CatalogStore::find_flow_node(&mut txn, node.id).await.unwrap().is_none());
54	}
55
56	#[tokio::test]
57	async fn test_delete_node_removes_from_index() {
58		let mut txn = create_test_command_transaction().await;
59		let _namespace = create_namespace(&mut txn, "test_namespace").await;
60		let flow = ensure_test_flow(&mut txn).await;
61
62		let node = create_flow_node(&mut txn, flow.id, 1, &[0x01]).await;
63
64		// Node should be in flow index
65		let nodes = CatalogStore::list_flow_nodes_by_flow(&mut txn, flow.id).await.unwrap();
66		assert_eq!(nodes.len(), 1);
67
68		// Delete node
69		CatalogStore::delete_flow_node(&mut txn, node.id).await.unwrap();
70
71		// Node should be removed from flow index
72		let nodes = CatalogStore::list_flow_nodes_by_flow(&mut txn, flow.id).await.unwrap();
73		assert!(nodes.is_empty());
74	}
75
76	#[tokio::test]
77	async fn test_delete_nonexistent_node() {
78		let mut txn = create_test_command_transaction().await;
79
80		// Deleting a non-existent node should succeed silently
81		CatalogStore::delete_flow_node(&mut txn, FlowNodeId(999)).await.unwrap();
82	}
83
84	#[tokio::test]
85	async fn test_delete_one_node_keeps_others() {
86		let mut txn = create_test_command_transaction().await;
87		let _namespace = create_namespace(&mut txn, "test_namespace").await;
88		let flow = ensure_test_flow(&mut txn).await;
89
90		let node1 = create_flow_node(&mut txn, flow.id, 1, &[0x01]).await;
91		let node2 = create_flow_node(&mut txn, flow.id, 4, &[0x02]).await;
92
93		// Delete first node
94		CatalogStore::delete_flow_node(&mut txn, node1.id).await.unwrap();
95
96		// First node should be gone, second should remain
97		assert!(CatalogStore::find_flow_node(&mut txn, node1.id).await.unwrap().is_none());
98		assert!(CatalogStore::find_flow_node(&mut txn, node2.id).await.unwrap().is_some());
99
100		// List should only have second node
101		let nodes = CatalogStore::list_flow_nodes_by_flow(&mut txn, flow.id).await.unwrap();
102		assert_eq!(nodes.len(), 1);
103		assert_eq!(nodes[0].id, node2.id);
104	}
105}