use async_trait::async_trait;
use std::collections::HashMap;
use std::time::SystemTime;
use crate::common::namespace::Namespace;
use crate::graph::{
config::GraphConfig,
error::Result,
types::{
CausalPath, ChangelogEntry, Community, Entity, ExternalRef, Relation, RetargetStats,
},
};
use crate::store::health::HealthReport;
#[derive(Debug, Clone, Default)]
pub struct EntitySearchOptions {
pub entity_type: Option<String>,
pub query: Option<String>,
pub limit: usize,
pub min_confidence: Option<f32>,
}
impl EntitySearchOptions {
pub fn new() -> Self {
Self { limit: 20, ..Default::default() }
}
pub fn with_type(mut self, t: impl Into<String>) -> Self {
self.entity_type = Some(t.into());
self
}
pub fn with_query(mut self, q: impl Into<String>) -> Self {
self.query = Some(q.into());
self
}
pub fn with_limit(mut self, limit: usize) -> Self {
self.limit = limit;
self
}
pub fn with_min_confidence(mut self, min: f32) -> Self {
self.min_confidence = Some(min);
self
}
}
#[derive(Debug, Clone, Default)]
pub struct RelationOptions {
pub from_id: Option<u64>,
pub to_id: Option<u64>,
pub relation_type: Option<String>,
pub min_confidence: Option<f32>,
pub current_only: Option<bool>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TraversalDirection {
Outgoing,
Incoming,
#[default]
Both,
}
#[derive(Debug, Clone)]
pub struct CausalOptions {
pub types: Option<Vec<String>>,
pub max_depth: usize,
pub max_paths: usize,
pub max_branching_factor: Option<usize>,
pub min_causal_strength: Option<f32>,
pub as_of: Option<SystemTime>,
}
impl Default for CausalOptions {
fn default() -> Self {
Self {
types: None,
max_depth: 5,
max_paths: 50,
max_branching_factor: None,
min_causal_strength: None,
as_of: None,
}
}
}
#[async_trait]
pub trait GraphAdapter: Send + Sync {
fn name(&self) -> &'static str;
fn is_connected(&self) -> bool;
fn config(&self) -> &GraphConfig;
async fn create_entity(
&self,
name: &str,
entity_type: &str,
properties: Option<crate::common::metadata::Metadata>,
namespace: Option<&Namespace>,
) -> Result<Entity>;
async fn find_entity(
&self,
id: u64,
namespace: Option<&Namespace>,
) -> Result<Option<Entity>>;
async fn find_entity_by_name(
&self,
name: &str,
namespace: Option<&Namespace>,
) -> Result<Option<Entity>>;
async fn search_entities(
&self,
options: EntitySearchOptions,
namespace: Option<&Namespace>,
) -> Result<Vec<Entity>>;
async fn update_entity(
&self,
id: u64,
updates: HashMap<String, serde_json::Value>,
namespace: Option<&Namespace>,
) -> Result<Option<Entity>>;
async fn delete_entity(
&self,
id: u64,
namespace: Option<&Namespace>,
) -> Result<bool>;
async fn create_relation(
&self,
from_id: u64,
to_id: u64,
relation_type: &str,
properties: Option<crate::common::metadata::Metadata>,
namespace: Option<&Namespace>,
) -> Result<Relation>;
async fn find_relations(
&self,
options: RelationOptions,
namespace: Option<&Namespace>,
) -> Result<Vec<Relation>>;
async fn update_relation(
&self,
id: u64,
updates: HashMap<String, serde_json::Value>,
namespace: Option<&Namespace>,
) -> Result<Option<Relation>>;
async fn delete_relation(
&self,
id: u64,
namespace: Option<&Namespace>,
) -> Result<bool>;
async fn upsert_relation_embedding(
&self,
relation_id: u64,
vector: Vec<f32>,
key: Option<&str>,
namespace: Option<&Namespace>,
) -> Result<Option<Relation>>;
async fn find_relations_by_embedding(
&self,
vector: &[f32],
limit: usize,
min_similarity: f32,
namespace: Option<&Namespace>,
) -> Result<Vec<Relation>>;
async fn neighbors(
&self,
entity_id: u64,
depth: usize,
direction: TraversalDirection,
namespace: Option<&Namespace>,
) -> Result<Vec<Entity>>;
async fn shortest_path(
&self,
from_id: u64,
to_id: u64,
namespace: Option<&Namespace>,
) -> Result<Vec<Entity>>;
async fn subgraph(
&self,
seed_ids: &[u64],
depth: usize,
namespace: Option<&Namespace>,
) -> Result<(Vec<Entity>, Vec<Relation>)>;
async fn causal_descendants(
&self,
entity_id: u64,
options: CausalOptions,
namespace: Option<&Namespace>,
) -> Result<Vec<CausalPath>>;
async fn causal_ancestors(
&self,
entity_id: u64,
options: CausalOptions,
namespace: Option<&Namespace>,
) -> Result<Vec<CausalPath>>;
async fn causal_paths(
&self,
from_id: u64,
to_id: u64,
options: CausalOptions,
namespace: Option<&Namespace>,
) -> Result<Vec<CausalPath>>;
async fn find_entities_as_of(
&self,
at: SystemTime,
options: EntitySearchOptions,
namespace: Option<&Namespace>,
) -> Result<Vec<Entity>>;
async fn find_relations_as_of(
&self,
at: SystemTime,
options: RelationOptions,
namespace: Option<&Namespace>,
) -> Result<Vec<Relation>>;
async fn supersede_entity(
&self,
old_id: u64,
new_attributes: HashMap<String, serde_json::Value>,
namespace: Option<&Namespace>,
) -> Result<Entity>;
async fn supersede_relation(
&self,
old_id: u64,
new_attributes: HashMap<String, serde_json::Value>,
namespace: Option<&Namespace>,
) -> Result<Relation>;
async fn retract_entity(
&self,
id: u64,
valid_to: Option<SystemTime>,
namespace: Option<&Namespace>,
) -> Result<Entity>;
async fn retract_relation(
&self,
id: u64,
valid_to: Option<SystemTime>,
namespace: Option<&Namespace>,
) -> Result<Relation>;
async fn changelog(
&self,
since: Option<SystemTime>,
until: Option<SystemTime>,
record_type: Option<&str>,
namespace: Option<&Namespace>,
) -> Result<Vec<ChangelogEntry>>;
async fn add_external_ref(
&self,
entity_id: u64,
ext_ref: ExternalRef,
namespace: Option<&Namespace>,
) -> Result<Entity>;
async fn find_by_external_ref(
&self,
source: &str,
external_id: &str,
active_only: bool,
namespace: Option<&Namespace>,
) -> Result<Vec<Entity>>;
async fn retarget_relations(
&self,
old_entity_id: u64,
new_entity_id: u64,
namespace: Option<&Namespace>,
) -> Result<RetargetStats>;
async fn detect_communities(
&self,
namespace: Option<&Namespace>,
) -> Result<Vec<Community>>;
async fn healthcheck(&self) -> HealthReport;
}