Skip to main content

aa_core/storage/
session_store.rs

1//! [`SessionStore`] — persistence for per-execution session records.
2
3use super::{AgentId, Result, SessionId};
4use async_trait::async_trait;
5
6/// A persisted record of a single agent execution session.
7///
8/// One record is created per execution run and ties together all governance
9/// events within that run. Backends key the record by its
10/// [`session_id`](SessionRecord::session_id).
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct SessionRecord {
13    /// Stable identifier for this execution run.
14    pub session_id: SessionId,
15    /// The agent that owns this session.
16    pub agent_id: AgentId,
17    /// Wall-clock start time of the session, in nanoseconds since the Unix epoch.
18    pub started_at_ns: u64,
19}
20
21/// Persists, loads, and deletes [`SessionRecord`]s.
22///
23/// The runtime saves a record when a session starts, loads it to resume
24/// governance context, and deletes it when the session ends.
25///
26/// # Example
27///
28/// ```
29/// use aa_core::storage::{Result, SessionId, SessionRecord, SessionStore, StorageError};
30/// use async_trait::async_trait;
31///
32/// /// A store that holds no sessions.
33/// struct EmptySessionStore;
34///
35/// #[async_trait]
36/// impl SessionStore for EmptySessionStore {
37///     async fn save(&self, _session: SessionRecord) -> Result<()> {
38///         Ok(())
39///     }
40///
41///     async fn load(&self, session_id: &SessionId) -> Result<SessionRecord> {
42///         Err(StorageError::NotFound(format!("{:?}", session_id.as_bytes())))
43///     }
44///
45///     async fn delete(&self, _session_id: &SessionId) -> Result<()> {
46///         Ok(())
47///     }
48/// }
49/// ```
50#[async_trait]
51pub trait SessionStore: Send + Sync {
52    /// Persist `session`, overwriting any record with the same session id.
53    async fn save(&self, session: SessionRecord) -> Result<()>;
54
55    /// Load the record for `session_id`.
56    ///
57    /// Returns [`StorageError::NotFound`](super::StorageError::NotFound) when no
58    /// record exists for the id.
59    async fn load(&self, session_id: &SessionId) -> Result<SessionRecord>;
60
61    /// Delete the record for `session_id`.
62    ///
63    /// Idempotent: deleting an absent session succeeds.
64    async fn delete(&self, session_id: &SessionId) -> Result<()>;
65}