Skip to main content

khive_db/backend/core_stores/
graph.rs

1use super::super::StorageBackend;
2use super::map_open_error;
3use async_trait::async_trait;
4use chrono::{DateTime, Utc};
5use khive_storage::graph::{
6    CommitAnnotationGuard, CommitAnnotationInsertOutcome, GraphStore, SymmetricEdgeUpdateOutcome,
7    SymmetricEdgeUpdateRequest,
8};
9use khive_storage::types::EdgeEndpointBaseCounts;
10use khive_storage::{
11    BatchWriteSummary, DeleteMode, DirectedNeighborHit, Edge, EdgeFilter, EdgeSeekPage,
12    EdgeSortField, EdgeUpsertRequest, EdgeUpsertResult, GraphPath, GuardedBatchOutcome,
13    GuardedEdgeBatchUpsertOutcome, GuardedEdgeUpsertOutcome, GuardedWriteOutcome, LinkId,
14    NeighborCursor, NeighborHit, NeighborQuery, Page, PageRequest, SeekCursor, SeekPage, SortOrder,
15    StorageCapability, StorageResult, TraversalRequest,
16};
17use khive_types::EdgeRelation;
18use uuid::Uuid;
19
20#[async_trait]
21impl GraphStore for StorageBackend {
22    async fn latest_annotating_note(
23        &self,
24        _node_id: Uuid,
25        _kind: &str,
26        _tag: &str,
27    ) -> StorageResult<Option<(Uuid, i64)>> {
28        self.graph()
29            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
30            .latest_annotating_note(_node_id, _kind, _tag)
31            .await
32    }
33
34    async fn latest_annotating_note_with_property(
35        &self,
36        _node_id: Uuid,
37        _kind: &str,
38        _tag: &str,
39        _property_key: &str,
40        _property_value: &str,
41    ) -> StorageResult<Option<(Uuid, i64)>> {
42        self.graph()
43            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
44            .latest_annotating_note_with_property(
45                _node_id,
46                _kind,
47                _tag,
48                _property_key,
49                _property_value,
50            )
51            .await
52    }
53
54    async fn upsert_edge(&self, edge: Edge) -> StorageResult<()> {
55        self.graph()
56            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
57            .upsert_edge(edge)
58            .await
59    }
60
61    async fn insert_edge_if_absent(&self, _edge: Edge) -> StorageResult<bool> {
62        self.graph()
63            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
64            .insert_edge_if_absent(_edge)
65            .await
66    }
67
68    async fn insert_commit_annotation_if_absent(
69        &self,
70        _edge: Edge,
71        _guard: CommitAnnotationGuard,
72    ) -> StorageResult<CommitAnnotationInsertOutcome> {
73        self.graph()
74            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
75            .insert_commit_annotation_if_absent(_edge, _guard)
76            .await
77    }
78
79    async fn upsert_edges(&self, edges: Vec<Edge>) -> StorageResult<BatchWriteSummary> {
80        self.graph()
81            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
82            .upsert_edges(edges)
83            .await
84    }
85
86    async fn upsert_edge_observed(
87        &self,
88        _request: EdgeUpsertRequest,
89    ) -> StorageResult<EdgeUpsertResult> {
90        self.graph()
91            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
92            .upsert_edge_observed(_request)
93            .await
94    }
95
96    async fn replace_edge_if_unchanged(
97        &self,
98        _edge: Edge,
99        _expected_updated_at: DateTime<Utc>,
100        _expected_deleted_at: Option<DateTime<Utc>>,
101    ) -> StorageResult<bool> {
102        self.graph()
103            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
104            .replace_edge_if_unchanged(_edge, _expected_updated_at, _expected_deleted_at)
105            .await
106    }
107
108    async fn update_symmetric_edge_if_unchanged(
109        &self,
110        _request: SymmetricEdgeUpdateRequest,
111    ) -> StorageResult<SymmetricEdgeUpdateOutcome> {
112        self.graph()
113            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
114            .update_symmetric_edge_if_unchanged(_request)
115            .await
116    }
117
118    async fn upsert_edge_guarded(&self, _edge: Edge) -> StorageResult<GuardedWriteOutcome> {
119        self.graph()
120            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
121            .upsert_edge_guarded(_edge)
122            .await
123    }
124
125    async fn upsert_edge_guarded_observed(
126        &self,
127        _request: EdgeUpsertRequest,
128    ) -> StorageResult<GuardedEdgeUpsertOutcome> {
129        self.graph()
130            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
131            .upsert_edge_guarded_observed(_request)
132            .await
133    }
134
135    async fn upsert_edges_guarded(&self, _edges: Vec<Edge>) -> StorageResult<GuardedBatchOutcome> {
136        self.graph()
137            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
138            .upsert_edges_guarded(_edges)
139            .await
140    }
141
142    async fn upsert_edges_guarded_observed(
143        &self,
144        _requests: Vec<EdgeUpsertRequest>,
145    ) -> StorageResult<GuardedEdgeBatchUpsertOutcome> {
146        self.graph()
147            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
148            .upsert_edges_guarded_observed(_requests)
149            .await
150    }
151
152    async fn get_edge(&self, id: LinkId) -> StorageResult<Option<Edge>> {
153        self.graph()
154            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
155            .get_edge(id)
156            .await
157    }
158
159    async fn get_edge_including_deleted(&self, id: LinkId) -> StorageResult<Option<Edge>> {
160        self.graph()
161            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
162            .get_edge_including_deleted(id)
163            .await
164    }
165
166    async fn get_edge_by_natural_key_including_deleted(
167        &self,
168        namespace: &str,
169        source_id: Uuid,
170        target_id: Uuid,
171        relation: EdgeRelation,
172    ) -> StorageResult<Option<Edge>> {
173        self.graph()
174            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
175            .get_edge_by_natural_key_including_deleted(namespace, source_id, target_id, relation)
176            .await
177    }
178
179    async fn delete_edge(&self, id: LinkId, mode: DeleteMode) -> StorageResult<bool> {
180        self.graph()
181            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
182            .delete_edge(id, mode)
183            .await
184    }
185
186    async fn query_edges(
187        &self,
188        filter: EdgeFilter,
189        sort: Vec<SortOrder<EdgeSortField>>,
190        page: PageRequest,
191    ) -> StorageResult<Page<Edge>> {
192        self.graph()
193            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
194            .query_edges(filter, sort, page)
195            .await
196    }
197
198    async fn query_edges_in_namespaces(
199        &self,
200        namespaces: &[String],
201        filter: EdgeFilter,
202        sort: Vec<SortOrder<EdgeSortField>>,
203        page: PageRequest,
204    ) -> StorageResult<Page<Edge>> {
205        self.graph()
206            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
207            .query_edges_in_namespaces(namespaces, filter, sort, page)
208            .await
209    }
210
211    async fn count_edges(&self, filter: EdgeFilter) -> StorageResult<u64> {
212        self.graph()
213            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
214            .count_edges(filter)
215            .await
216    }
217
218    async fn count_edges_in_namespaces(
219        &self,
220        namespaces: &[String],
221        filter: EdgeFilter,
222    ) -> StorageResult<u64> {
223        self.graph()
224            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
225            .count_edges_in_namespaces(namespaces, filter)
226            .await
227    }
228
229    async fn count_edges_by_relation(&self) -> StorageResult<Vec<(EdgeRelation, u64)>> {
230        self.graph()
231            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
232            .count_edges_by_relation()
233            .await
234    }
235
236    async fn count_edges_by_relation_in_namespaces(
237        &self,
238        namespaces: &[String],
239    ) -> StorageResult<Vec<(EdgeRelation, u64)>> {
240        self.graph()
241            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
242            .count_edges_by_relation_in_namespaces(namespaces)
243            .await
244    }
245
246    async fn count_edges_by_endpoint_base(&self) -> StorageResult<EdgeEndpointBaseCounts> {
247        self.graph()
248            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
249            .count_edges_by_endpoint_base()
250            .await
251    }
252
253    async fn count_edges_by_endpoint_base_in_namespaces(
254        &self,
255        namespaces: &[String],
256    ) -> StorageResult<EdgeEndpointBaseCounts> {
257        self.graph()
258            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
259            .count_edges_by_endpoint_base_in_namespaces(namespaces)
260            .await
261    }
262
263    async fn count_edges_by_relation_and_endpoint_base_in_namespaces(
264        &self,
265        namespaces: &[String],
266    ) -> StorageResult<Vec<(EdgeRelation, EdgeEndpointBaseCounts)>> {
267        self.graph()
268            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
269            .count_edges_by_relation_and_endpoint_base_in_namespaces(namespaces)
270            .await
271    }
272
273    async fn query_edges_after(
274        &self,
275        filter: EdgeFilter,
276        after: Option<Uuid>,
277        limit: u32,
278    ) -> StorageResult<EdgeSeekPage> {
279        self.graph()
280            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
281            .query_edges_after(filter, after, limit)
282            .await
283    }
284
285    async fn edge_sequence(&self, _id: Uuid) -> StorageResult<Option<i64>> {
286        self.graph()
287            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
288            .edge_sequence(_id)
289            .await
290    }
291
292    async fn edge_sequences(&self, ids: &[Uuid]) -> StorageResult<Vec<(Uuid, i64)>> {
293        self.graph()
294            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
295            .edge_sequences(ids)
296            .await
297    }
298
299    async fn query_edges_sequence_after(
300        &self,
301        _filter: EdgeFilter,
302        _after: Option<SeekCursor>,
303        _limit: u32,
304    ) -> StorageResult<SeekPage<Edge>> {
305        self.graph()
306            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
307            .query_edges_sequence_after(_filter, _after, _limit)
308            .await
309    }
310
311    async fn neighbors(
312        &self,
313        node_id: Uuid,
314        query: NeighborQuery,
315    ) -> StorageResult<Vec<NeighborHit>> {
316        self.graph()
317            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
318            .neighbors(node_id, query)
319            .await
320    }
321
322    async fn neighbors_page(
323        &self,
324        node_id: Uuid,
325        query: NeighborQuery,
326        after: Option<NeighborCursor>,
327        neighbor_kinds: Option<Vec<String>>,
328    ) -> StorageResult<Vec<NeighborHit>> {
329        self.graph()
330            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
331            .neighbors_page(node_id, query, after, neighbor_kinds)
332            .await
333    }
334
335    async fn neighbors_both_directions(
336        &self,
337        node_id: Uuid,
338        query: NeighborQuery,
339    ) -> StorageResult<Vec<DirectedNeighborHit>> {
340        self.graph()
341            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
342            .neighbors_both_directions(node_id, query)
343            .await
344    }
345
346    async fn get_edges(&self, ids: &[LinkId]) -> StorageResult<Vec<Edge>> {
347        self.graph()
348            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
349            .get_edges(ids)
350            .await
351    }
352
353    async fn get_edge_read_outcomes(
354        &self,
355        ids: &[LinkId],
356    ) -> StorageResult<Vec<StorageResult<Option<Edge>>>> {
357        self.graph()
358            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
359            .get_edge_read_outcomes(ids)
360            .await
361    }
362
363    async fn batch_neighbors(
364        &self,
365        sources: &[Uuid],
366        query: NeighborQuery,
367    ) -> StorageResult<Vec<(Uuid, NeighborHit)>> {
368        self.graph()
369            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
370            .batch_neighbors(sources, query)
371            .await
372    }
373
374    async fn traverse(&self, request: TraversalRequest) -> StorageResult<Vec<GraphPath>> {
375        self.graph()
376            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
377            .traverse(request)
378            .await
379    }
380
381    async fn purge_incident_edges(&self, node_id: Uuid) -> StorageResult<u64> {
382        self.graph()
383            .map_err(|error| map_open_error(error, StorageCapability::Graph, "graph"))?
384            .purge_incident_edges(node_id)
385            .await
386    }
387}