agent_office/storage/
mod.rs1use crate::domain::{Edge, GraphQuery, Node, NodeId, EdgeId};
2use async_trait::async_trait;
3use thiserror::Error;
4use chrono::{DateTime, Utc};
5
6#[derive(Debug, Clone)]
8pub struct SearchQuery {
9 pub node_types: Vec<String>,
11 pub search_text: Option<String>,
13 pub search_fields: Vec<String>,
15 pub created_after: Option<DateTime<Utc>>,
17 pub created_before: Option<DateTime<Utc>>,
19 pub updated_after: Option<DateTime<Utc>>,
21 pub property_filters: Vec<(String, String)>,
23 pub limit: usize,
25 pub offset: usize,
27 pub order_by: OrderBy,
29 pub order_direction: OrderDirection,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq)]
34pub enum OrderBy {
35 CreatedAt,
36 UpdatedAt,
37 Relevance,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq)]
41pub enum OrderDirection {
42 Asc,
43 Desc,
44}
45
46impl Default for SearchQuery {
47 fn default() -> Self {
48 Self {
49 node_types: vec![],
50 search_text: None,
51 search_fields: vec![],
52 created_after: None,
53 created_before: None,
54 updated_after: None,
55 property_filters: vec![],
56 limit: 50,
57 offset: 0,
58 order_by: OrderBy::UpdatedAt,
59 order_direction: OrderDirection::Desc,
60 }
61 }
62}
63
64#[derive(Debug, Clone)]
66pub struct SearchResults<T> {
67 pub items: Vec<T>,
68 pub total_count: usize,
69 pub returned_count: usize,
70 pub has_more: bool,
71 pub limit: usize,
72 pub offset: usize,
73}
74
75#[derive(Error, Debug)]
76pub enum StorageError {
77 #[error("Node not found: {0}")]
78 NodeNotFound(NodeId),
79
80 #[error("Edge not found: {0}")]
81 EdgeNotFound(EdgeId),
82
83 #[error("Database error: {0}")]
84 DatabaseError(String),
85
86 #[error("Serialization error: {0}")]
87 SerializationError(String),
88
89 #[error("Constraint violation: {0}")]
90 ConstraintViolation(String),
91}
92
93pub type Result<T> = std::result::Result<T, StorageError>;
94
95#[async_trait]
96pub trait GraphStorage: Send + Sync {
97 async fn create_node(&self, node: &Node) -> Result<Node>;
99 async fn get_node(&self, id: NodeId) -> Result<Node>;
100 async fn update_node(&self, node: &Node) -> Result<Node>;
101 async fn delete_node(&self, id: NodeId) -> Result<()>;
102 async fn query_nodes(&self, query: &GraphQuery) -> Result<Vec<Node>>;
103
104 async fn create_edge(&self, edge: &Edge) -> Result<Edge>;
106 async fn get_edge(&self, id: EdgeId) -> Result<Edge>;
107 async fn delete_edge(&self, id: EdgeId) -> Result<()>;
108 async fn get_edges_from(&self, node_id: NodeId, edge_type: Option<&str>) -> Result<Vec<Edge>>;
109 async fn get_edges_to(&self, node_id: NodeId, edge_type: Option<&str>) -> Result<Vec<Edge>>;
110
111 async fn get_neighbors(
113 &self,
114 node_id: NodeId,
115 edge_type: Option<&str>,
116 direction: EdgeDirection,
117 ) -> Result<Vec<Node>>;
118
119 async fn search_nodes(&self, query: &SearchQuery) -> Result<SearchResults<Node>>;
121
122 async fn count_nodes(&self, query: &SearchQuery) -> Result<usize>;
124}
125
126#[derive(Debug, Clone, Copy, PartialEq)]
127pub enum EdgeDirection {
128 Outgoing,
129 Incoming,
130 Both,
131}
132
133#[async_trait]
134pub trait TransactionalGraphStorage: GraphStorage {
135 async fn begin_transaction(&self) -> Result<Box<dyn GraphTransaction>>;
136}
137
138#[async_trait]
139pub trait GraphTransaction: Send + Sync {
140 async fn commit(self: Box<Self>) -> Result<()>;
141 async fn rollback(self: Box<Self>) -> Result<()>;
142}
143
144pub mod memory;
145pub mod postgres;