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}