nexus_common/db/graph/exec.rs
1use crate::db::get_neo4j_graph;
2use crate::types::DynError;
3use neo4rs::Query;
4use serde::de::DeserializeOwned;
5
6/// Represents the outcome of a mutation-like query in the graph database.
7#[derive(Debug)]
8pub enum OperationOutcome {
9 /// The query found and updated an existing node/relationship.
10 Updated,
11 /// This variant represents a structural mutation where the node/relationship
12 /// did not exist before the operation (creation) or no longer exists after the operation (deletion)
13 CreatedOrDeleted,
14 /// A required node/relationship was not found, indicating a missing dependency
15 /// (often due to the node/relationship not yet being indexed or otherwise unavailable).
16 MissingDependency,
17}
18
19/// Executes a graph query expected to return exactly one row containing a boolean column named
20/// "flag". Interprets the boolean as follows:
21///
22/// - `true` => Returns [`OperationOutcome::Updated`]
23/// - `false` => Returns [`OperationOutcome::CreatedOrDeleted`]
24///
25/// If no rows are returned, this function returns [`OperationOutcome::MissingDependency`], typically
26/// indicating a missing dependency or an unmatched query condition.
27pub async fn execute_graph_operation(query: Query) -> Result<OperationOutcome, DynError> {
28 let mut result;
29 {
30 let graph = get_neo4j_graph()?;
31 let graph = graph.lock().await;
32 result = graph.execute(query).await?;
33 }
34
35 match result.next().await? {
36 // The "flag" field indicates a specific condition in the query
37 Some(row) => match row.get("flag")? {
38 true => Ok(OperationOutcome::Updated),
39 false => Ok(OperationOutcome::CreatedOrDeleted),
40 },
41 None => Ok(OperationOutcome::MissingDependency),
42 }
43}
44
45// Exec a graph query without a return
46pub async fn exec_single_row(query: Query) -> Result<(), DynError> {
47 let graph = get_neo4j_graph()?;
48 let graph = graph.lock().await;
49 let mut result = graph.execute(query).await?;
50 result.next().await?;
51 Ok(())
52}
53
54// Generic function to retrieve data from Neo4J
55pub async fn retrieve_from_graph<T>(query: Query, key: &str) -> Result<Option<T>, DynError>
56where
57 // Key point: DeserializeOwned ensures we can deserialize into any type that implements it
58 T: DeserializeOwned + Send + Sync,
59{
60 let mut result;
61 {
62 let graph = get_neo4j_graph()?;
63 let graph = graph.lock().await;
64 result = graph.execute(query).await?;
65 }
66
67 if let Some(row) = result.next().await? {
68 let data: T = row.get(key)?;
69 return Ok(Some(data));
70 }
71
72 Ok(None)
73}