use anyhow::Result;
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use crate::domain::models::{
AvecState, BatchRekeyResult, ChangeQueryResult, ConnectorMetadata, NodeQuery, NodeUpsertResult,
SttpNode, SyncCheckpoint, SyncCursor, ValidationResult,
};
#[async_trait]
pub trait NodeStore: Send + Sync {
async fn query_nodes_async(&self, query: NodeQuery) -> Result<Vec<SttpNode>>;
async fn store_async(&self, node: SttpNode) -> Result<String> {
Ok(self.upsert_node_async(node).await?.node_id)
}
async fn upsert_node_async(&self, node: SttpNode) -> Result<NodeUpsertResult>;
async fn get_by_resonance_async(
&self,
session_id: &str,
current_avec: AvecState,
from_utc: Option<DateTime<Utc>>,
to_utc: Option<DateTime<Utc>>,
tiers: Option<&[String]>,
limit: usize,
) -> Result<Vec<SttpNode>>;
async fn get_by_resonance_global_async(
&self,
current_avec: AvecState,
from_utc: Option<DateTime<Utc>>,
to_utc: Option<DateTime<Utc>>,
tiers: Option<&[String]>,
limit: usize,
) -> Result<Vec<SttpNode>>;
async fn get_by_hybrid_async(
&self,
session_id: &str,
current_avec: AvecState,
from_utc: Option<DateTime<Utc>>,
to_utc: Option<DateTime<Utc>>,
tiers: Option<&[String]>,
query_embedding: Option<&[f32]>,
alpha: f32,
beta: f32,
limit: usize,
) -> Result<Vec<SttpNode>> {
let _ = (query_embedding, alpha, beta);
self.get_by_resonance_async(session_id, current_avec, from_utc, to_utc, tiers, limit)
.await
}
async fn get_by_hybrid_global_async(
&self,
current_avec: AvecState,
from_utc: Option<DateTime<Utc>>,
to_utc: Option<DateTime<Utc>>,
tiers: Option<&[String]>,
query_embedding: Option<&[f32]>,
alpha: f32,
beta: f32,
limit: usize,
) -> Result<Vec<SttpNode>> {
let _ = (query_embedding, alpha, beta);
self.get_by_resonance_global_async(current_avec, from_utc, to_utc, tiers, limit)
.await
}
async fn list_nodes_async(
&self,
limit: usize,
session_id: Option<&str>,
) -> Result<Vec<SttpNode>>;
async fn get_last_avec_async(&self, session_id: &str) -> Result<Option<AvecState>>;
async fn get_trigger_history_async(&self, session_id: &str) -> Result<Vec<String>>;
async fn store_calibration_async(
&self,
session_id: &str,
avec: AvecState,
trigger: &str,
) -> Result<()>;
async fn query_changes_since_async(
&self,
session_id: &str,
cursor: Option<SyncCursor>,
limit: usize,
) -> Result<ChangeQueryResult>;
async fn get_checkpoint_async(
&self,
session_id: &str,
connector_id: &str,
) -> Result<Option<SyncCheckpoint>>;
async fn put_checkpoint_async(&self, checkpoint: SyncCheckpoint) -> Result<()>;
async fn batch_rekey_scopes_async(
&self,
node_ids: Vec<String>,
target_tenant_id: &str,
target_session_id: &str,
dry_run: bool,
allow_merge: bool,
) -> Result<BatchRekeyResult>;
}
#[async_trait]
pub trait EmbeddingProvider: Send + Sync {
fn model_name(&self) -> &str;
async fn embed_async(&self, text: &str) -> Result<Vec<f32>>;
}
#[async_trait]
pub trait NodeStoreInitializer: Send + Sync {
async fn initialize_async(&self) -> Result<()>;
}
pub trait NodeValidator: Send + Sync {
fn validate(&self, raw_node: &str) -> ValidationResult;
fn verify_psi(&self, node: &SttpNode) -> bool;
}
#[async_trait]
pub trait SyncChangeSource: Send + Sync {
async fn read_changes_async(
&self,
session_id: &str,
connector_id: &str,
cursor: Option<SyncCursor>,
limit: usize,
) -> Result<ChangeQueryResult>;
}
pub trait SyncCoordinatorPolicy: Send + Sync {
fn should_accept_node(&self, _node: &SttpNode) -> bool {
true
}
fn checkpoint_metadata(
&self,
_session_id: &str,
_connector_id: &str,
previous: Option<&SyncCheckpoint>,
_last_applied_node: Option<&SttpNode>,
_next_cursor: Option<&SyncCursor>,
) -> Option<ConnectorMetadata> {
previous.and_then(|checkpoint| checkpoint.metadata.clone())
}
}