use crate::{effect::Scope, error::StateError};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
#[async_trait]
pub trait StateStore: Send + Sync {
async fn read(&self, scope: &Scope, key: &str)
-> Result<Option<serde_json::Value>, StateError>;
async fn write(
&self,
scope: &Scope,
key: &str,
value: serde_json::Value,
) -> Result<(), StateError>;
async fn delete(&self, scope: &Scope, key: &str) -> Result<(), StateError>;
async fn list(&self, scope: &Scope, prefix: &str) -> Result<Vec<String>, StateError>;
async fn search(
&self,
scope: &Scope,
query: &str,
limit: usize,
) -> Result<Vec<SearchResult>, StateError>;
}
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchResult {
pub key: String,
pub score: f64,
pub snippet: Option<String>,
}
impl SearchResult {
pub fn new(key: impl Into<String>, score: f64) -> Self {
Self {
key: key.into(),
score,
snippet: None,
}
}
}
#[async_trait]
pub trait StateReader: Send + Sync {
async fn read(&self, scope: &Scope, key: &str)
-> Result<Option<serde_json::Value>, StateError>;
async fn list(&self, scope: &Scope, prefix: &str) -> Result<Vec<String>, StateError>;
async fn search(
&self,
scope: &Scope,
query: &str,
limit: usize,
) -> Result<Vec<SearchResult>, StateError>;
}
#[async_trait]
impl<T: StateStore> StateReader for T {
async fn read(
&self,
scope: &Scope,
key: &str,
) -> Result<Option<serde_json::Value>, StateError> {
StateStore::read(self, scope, key).await
}
async fn list(&self, scope: &Scope, prefix: &str) -> Result<Vec<String>, StateError> {
StateStore::list(self, scope, prefix).await
}
async fn search(
&self,
scope: &Scope,
query: &str,
limit: usize,
) -> Result<Vec<SearchResult>, StateError> {
StateStore::search(self, scope, query, limit).await
}
}