Skip to main content

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}