From 2f81b7676d72f43570b36b668e093f463b6b9d36 Mon Sep 17 00:00:00 2001 From: 112batuhan Date: Thu, 28 Nov 2024 20:53:16 +0300 Subject: [PATCH] feat: combining graph query to keep nodes and edges consistent --- src/database/graph_vizualizer.rs | 33 ++++++++++++++++++-------------- src/handlers/graph_vizualizer.rs | 21 ++------------------ 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/database/graph_vizualizer.rs b/src/database/graph_vizualizer.rs index 941db3e..379f3f7 100644 --- a/src/database/graph_vizualizer.rs +++ b/src/database/graph_vizualizer.rs @@ -21,9 +21,19 @@ pub struct GraphInfluence { influence_type: u8, } +#[derive(Serialize, JsonSchema, Clone)] +pub struct GraphData { + pub nodes: Vec, + pub links: Vec, +} + impl DatabaseClient { - pub async fn get_users_for_graph(&self) -> Result, AppError> { - let graph_users: Vec = self + /// These two select queries are combined into one. The goal is to keep the data consistent + /// with each other to avoid errors in graphs. It's an edge case but can happen if load is + /// high. And since we cache the results, the error will stay on UI for the duration of the + /// cache. Not optimal. If it happens regardless, then use transactions. + pub async fn get_graph_data(&self) -> Result { + let mut query_result = self .db .query( " @@ -37,19 +47,14 @@ impl DatabaseClient { WHERE count(<-influenced_by) > 0 OR count(->influenced_by) > 0; + + SELECT meta::id(in) AS source, meta::id(out) AS target, influence_type FROM influenced_by; ", ) - .await? - .take(0)?; - Ok(graph_users) - } - - pub async fn get_influences_for_graph(&self) -> Result, AppError> { - let graph_influences: Vec = self - .db - .query("SELECT meta::id(in) AS source, meta::id(out) AS target, influence_type FROM influenced_by;") - .await? - .take(0)?; - Ok(graph_influences) + .await?; + Ok(GraphData { + nodes: query_result.take(0)?, + links: query_result.take(1)?, + }) } } diff --git a/src/handlers/graph_vizualizer.rs b/src/handlers/graph_vizualizer.rs index 4bdc737..f99e9f6 100644 --- a/src/handlers/graph_vizualizer.rs +++ b/src/handlers/graph_vizualizer.rs @@ -4,21 +4,8 @@ use std::{ }; use axum::{extract::State, Json}; -use futures::try_join; -use schemars::JsonSchema; -use serde::Serialize; -use crate::{ - database::graph_vizualizer::{GraphInfluence, GraphUser}, - error::AppError, - AppState, -}; - -#[derive(Serialize, JsonSchema, Clone)] -pub struct GraphData { - pub nodes: Vec, - pub links: Vec, -} +use crate::{database::graph_vizualizer::GraphData, error::AppError, AppState}; pub struct GraphCacheInner { pub data: Option, @@ -65,11 +52,7 @@ pub async fn get_graph_data( return Ok(Json(cached_graph)); } - let (nodes, links) = try_join!( - state.db.get_users_for_graph(), - state.db.get_influences_for_graph() - )?; - let graph_data = GraphData { nodes, links }; + let graph_data = state.db.get_graph_data().await?; state.graph_cache.update(graph_data.clone())?; Ok(Json(graph_data))