use async_trait::async_trait;
use serde_json::Value;
use crate::error::SnapshotError;
use crate::id::AgentId;
#[async_trait]
pub trait StateProvider: Send + Sync + 'static {
async fn capture_extract_cursor(
&self,
agent_id: &AgentId,
) -> Result<Option<Value>, SnapshotError>;
async fn capture_last_dream_run(
&self,
agent_id: &AgentId,
) -> Result<Option<Value>, SnapshotError>;
async fn restore_extract_cursor(
&self,
agent_id: &AgentId,
value: Value,
) -> Result<(), SnapshotError>;
async fn restore_dream_run(
&self,
agent_id: &AgentId,
value: Value,
) -> Result<(), SnapshotError>;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct NoopStateProvider;
#[async_trait]
impl StateProvider for NoopStateProvider {
async fn capture_extract_cursor(
&self,
_agent_id: &AgentId,
) -> Result<Option<Value>, SnapshotError> {
Ok(None)
}
async fn capture_last_dream_run(
&self,
_agent_id: &AgentId,
) -> Result<Option<Value>, SnapshotError> {
Ok(None)
}
async fn restore_extract_cursor(
&self,
_agent_id: &AgentId,
_value: Value,
) -> Result<(), SnapshotError> {
Ok(())
}
async fn restore_dream_run(
&self,
_agent_id: &AgentId,
_value: Value,
) -> Result<(), SnapshotError> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[tokio::test]
async fn noop_provider_returns_none_on_capture() {
let p = NoopStateProvider;
let id = "ana".to_string();
assert!(p.capture_extract_cursor(&id).await.unwrap().is_none());
assert!(p.capture_last_dream_run(&id).await.unwrap().is_none());
}
#[tokio::test]
async fn noop_provider_accepts_restore_payloads() {
let p = NoopStateProvider;
let id = "ana".to_string();
p.restore_extract_cursor(&id, serde_json::json!({"k": 1}))
.await
.unwrap();
p.restore_dream_run(&id, serde_json::json!({"k": 2}))
.await
.unwrap();
}
#[tokio::test]
async fn dyn_provider_can_be_held_as_arc() {
let p: Arc<dyn StateProvider> = Arc::new(NoopStateProvider);
let id = "ana".to_string();
assert!(p.capture_extract_cursor(&id).await.unwrap().is_none());
}
}