use std::future::Future;
use std::pin::Pin;
use tea_policy::{ActorId, PolicyGrant};
use tea_protocol::{RecordEnvelope, SessionId, SessionSequence};
use crate::{
ApprovalArtifactEntry, GrantJournalEntry, MaterializedSessionState, SessionStoreError,
};
pub type SessionStoreFuture<'a, T> =
Pin<Box<dyn Future<Output = Result<T, SessionStoreError>> + Send + 'a>>;
#[derive(Debug, Clone)]
pub struct AppendTransaction {
session_id: SessionId,
expected_sequence: Option<SessionSequence>,
records: Vec<RecordEnvelope>,
expected_journal_revision: Option<u64>,
approval_artifacts: Vec<ApprovalArtifactEntry>,
grant_entries: Vec<GrantJournalEntry>,
}
impl AppendTransaction {
#[must_use]
pub fn new(
session_id: SessionId,
expected_sequence: Option<SessionSequence>,
records: Vec<RecordEnvelope>,
) -> Self {
Self {
session_id,
expected_sequence,
records,
expected_journal_revision: None,
approval_artifacts: Vec::new(),
grant_entries: Vec::new(),
}
}
#[must_use]
pub const fn with_expected_journal_revision(mut self, revision: u64) -> Self {
self.expected_journal_revision = Some(revision);
self
}
#[must_use]
pub fn with_approval_artifacts(
mut self,
entries: impl IntoIterator<Item = ApprovalArtifactEntry>,
) -> Self {
self.approval_artifacts = entries.into_iter().collect();
self
}
#[must_use]
pub fn with_grant_entries(
mut self,
entries: impl IntoIterator<Item = GrantJournalEntry>,
) -> Self {
self.grant_entries = entries.into_iter().collect();
self
}
#[must_use]
pub const fn session_id(&self) -> SessionId {
self.session_id
}
#[must_use]
pub const fn expected_sequence(&self) -> Option<SessionSequence> {
self.expected_sequence
}
#[must_use]
pub fn records(&self) -> &[RecordEnvelope] {
&self.records
}
#[must_use]
pub const fn expected_journal_revision(&self) -> Option<u64> {
self.expected_journal_revision
}
#[must_use]
pub fn approval_artifacts(&self) -> &[ApprovalArtifactEntry] {
&self.approval_artifacts
}
#[must_use]
pub fn grant_entries(&self) -> &[GrantJournalEntry] {
&self.grant_entries
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct AppendOutcome {
previous_sequence: Option<SessionSequence>,
current_sequence: SessionSequence,
state: MaterializedSessionState,
journal_revision: u64,
}
impl AppendOutcome {
pub(crate) const fn new(
previous_sequence: Option<SessionSequence>,
current_sequence: SessionSequence,
state: MaterializedSessionState,
journal_revision: u64,
) -> Self {
Self {
previous_sequence,
current_sequence,
state,
journal_revision,
}
}
#[must_use]
pub const fn previous_sequence(&self) -> Option<SessionSequence> {
self.previous_sequence
}
#[must_use]
pub const fn current_sequence(&self) -> SessionSequence {
self.current_sequence
}
#[must_use]
pub const fn journal_revision(&self) -> u64 {
self.journal_revision
}
#[must_use]
pub const fn state(&self) -> &MaterializedSessionState {
&self.state
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SessionSnapshot {
records: Vec<RecordEnvelope>,
state: MaterializedSessionState,
approval_artifacts: Vec<ApprovalArtifactEntry>,
grant_journal: Vec<GrantJournalEntry>,
active_grants: Vec<PolicyGrant>,
journal_revision: u64,
}
impl SessionSnapshot {
pub(crate) const fn new(
records: Vec<RecordEnvelope>,
state: MaterializedSessionState,
approval_artifacts: Vec<ApprovalArtifactEntry>,
grant_journal: Vec<GrantJournalEntry>,
active_grants: Vec<PolicyGrant>,
journal_revision: u64,
) -> Self {
Self {
records,
state,
approval_artifacts,
grant_journal,
active_grants,
journal_revision,
}
}
#[must_use]
pub fn records(&self) -> &[RecordEnvelope] {
&self.records
}
#[must_use]
pub const fn state(&self) -> &MaterializedSessionState {
&self.state
}
#[must_use]
pub fn approval_artifacts(&self) -> &[ApprovalArtifactEntry] {
&self.approval_artifacts
}
#[must_use]
pub fn grant_journal(&self) -> &[GrantJournalEntry] {
&self.grant_journal
}
#[must_use]
pub const fn journal_revision(&self) -> u64 {
self.journal_revision
}
#[must_use]
pub fn active_grants(&self) -> &[PolicyGrant] {
&self.active_grants
}
}
pub trait SessionStore: std::fmt::Debug + Send + Sync {
fn load(&self, session_id: SessionId) -> SessionStoreFuture<'_, SessionSnapshot>;
fn append(&self, transaction: AppendTransaction) -> SessionStoreFuture<'_, AppendOutcome>;
fn active_grants_for_actor(
&self,
actor_id: ActorId,
) -> SessionStoreFuture<'_, Vec<PolicyGrant>>;
}