1use anyhow::Result;
2use async_trait::async_trait;
3use chrono::{DateTime, Utc};
4
5use crate::domain::models::{
6 AvecState, BatchRekeyResult, ChangeQueryResult, ConnectorMetadata, NodeQuery, NodeUpsertResult,
7 SttpNode, SyncCheckpoint, SyncCursor, ValidationResult,
8};
9
10#[async_trait]
15pub trait NodeStore: Send + Sync {
16 async fn query_nodes_async(&self, query: NodeQuery) -> Result<Vec<SttpNode>>;
18
19 async fn store_async(&self, node: SttpNode) -> Result<String> {
21 Ok(self.upsert_node_async(node).await?.node_id)
22 }
23
24 async fn upsert_node_async(&self, node: SttpNode) -> Result<NodeUpsertResult>;
26
27 async fn get_by_resonance_async(
29 &self,
30 session_id: &str,
31 current_avec: AvecState,
32 from_utc: Option<DateTime<Utc>>,
33 to_utc: Option<DateTime<Utc>>,
34 tiers: Option<&[String]>,
35 limit: usize,
36 ) -> Result<Vec<SttpNode>>;
37
38 async fn get_by_resonance_global_async(
40 &self,
41 current_avec: AvecState,
42 from_utc: Option<DateTime<Utc>>,
43 to_utc: Option<DateTime<Utc>>,
44 tiers: Option<&[String]>,
45 limit: usize,
46 ) -> Result<Vec<SttpNode>>;
47
48 async fn get_by_hybrid_async(
54 &self,
55 session_id: &str,
56 current_avec: AvecState,
57 from_utc: Option<DateTime<Utc>>,
58 to_utc: Option<DateTime<Utc>>,
59 tiers: Option<&[String]>,
60 query_embedding: Option<&[f32]>,
61 alpha: f32,
62 beta: f32,
63 limit: usize,
64 ) -> Result<Vec<SttpNode>> {
65 let _ = (query_embedding, alpha, beta);
66 self.get_by_resonance_async(session_id, current_avec, from_utc, to_utc, tiers, limit)
67 .await
68 }
69
70 async fn get_by_hybrid_global_async(
72 &self,
73 current_avec: AvecState,
74 from_utc: Option<DateTime<Utc>>,
75 to_utc: Option<DateTime<Utc>>,
76 tiers: Option<&[String]>,
77 query_embedding: Option<&[f32]>,
78 alpha: f32,
79 beta: f32,
80 limit: usize,
81 ) -> Result<Vec<SttpNode>> {
82 let _ = (query_embedding, alpha, beta);
83 self.get_by_resonance_global_async(current_avec, from_utc, to_utc, tiers, limit)
84 .await
85 }
86
87 async fn list_nodes_async(
89 &self,
90 limit: usize,
91 session_id: Option<&str>,
92 ) -> Result<Vec<SttpNode>>;
93
94 async fn get_last_avec_async(&self, session_id: &str) -> Result<Option<AvecState>>;
96
97 async fn get_trigger_history_async(&self, session_id: &str) -> Result<Vec<String>>;
99
100 async fn store_calibration_async(
102 &self,
103 session_id: &str,
104 avec: AvecState,
105 trigger: &str,
106 ) -> Result<()>;
107
108 async fn query_changes_since_async(
110 &self,
111 session_id: &str,
112 cursor: Option<SyncCursor>,
113 limit: usize,
114 ) -> Result<ChangeQueryResult>;
115
116 async fn get_checkpoint_async(
118 &self,
119 session_id: &str,
120 connector_id: &str,
121 ) -> Result<Option<SyncCheckpoint>>;
122
123 async fn put_checkpoint_async(&self, checkpoint: SyncCheckpoint) -> Result<()>;
125
126 async fn batch_rekey_scopes_async(
131 &self,
132 node_ids: Vec<String>,
133 target_tenant_id: &str,
134 target_session_id: &str,
135 dry_run: bool,
136 allow_merge: bool,
137 ) -> Result<BatchRekeyResult>;
138}
139
140#[async_trait]
141pub trait EmbeddingProvider: Send + Sync {
142 fn model_name(&self) -> &str;
143 async fn embed_async(&self, text: &str) -> Result<Vec<f32>>;
144}
145
146#[async_trait]
150pub trait NodeStoreInitializer: Send + Sync {
151 async fn initialize_async(&self) -> Result<()>;
152}
153
154pub trait NodeValidator: Send + Sync {
156 fn validate(&self, raw_node: &str) -> ValidationResult;
158 fn verify_psi(&self, node: &SttpNode) -> bool;
160}
161
162#[async_trait]
163pub trait SyncChangeSource: Send + Sync {
164 async fn read_changes_async(
165 &self,
166 session_id: &str,
167 connector_id: &str,
168 cursor: Option<SyncCursor>,
169 limit: usize,
170 ) -> Result<ChangeQueryResult>;
171}
172
173pub trait SyncCoordinatorPolicy: Send + Sync {
174 fn should_accept_node(&self, _node: &SttpNode) -> bool {
175 true
176 }
177
178 fn checkpoint_metadata(
179 &self,
180 _session_id: &str,
181 _connector_id: &str,
182 previous: Option<&SyncCheckpoint>,
183 _last_applied_node: Option<&SttpNode>,
184 _next_cursor: Option<&SyncCursor>,
185 ) -> Option<ConnectorMetadata> {
186 previous.and_then(|checkpoint| checkpoint.metadata.clone())
187 }
188}