use super::{
AgentDraftStore, ApprovalEvidence, ApprovalTransition, AtomicDraftStore, DraftError,
issuer_approval,
};
use lys_pass::drafts::{ApprovedDraft, Execution};
use std::num::NonZeroUsize;
pub struct TargetDraftStore {
pub agents: AgentDraftStore,
pub sites: crate::services::lifecycle::site::executor::SiteDraftStore,
}
impl TargetDraftStore {
fn target(&mut self, draft: &ApprovedDraft) -> Result<&mut dyn AtomicDraftStore, DraftError> {
match draft.target.kind.as_str() {
"liminal.agent" => Ok(&mut self.agents),
"liminal.network" if draft.target.action == "create_site" => Ok(&mut self.sites),
"liminal.service" | "liminal.template" => Ok(&mut self.sites),
_ => Err(DraftError::Contract),
}
}
}
impl AtomicDraftStore for TargetDraftStore {
fn receipt(&self, id: &str) -> Result<Option<Execution>, DraftError> {
let agent = self.agents.receipt(id)?;
let site = self.sites.receipt(id)?;
if agent.is_some() && site.is_some() {
return Err(DraftError::ReceiptMismatch);
}
Ok(agent.or(site))
}
fn approval(&self, draft: &ApprovedDraft) -> Result<ApprovalEvidence, DraftError> {
issuer_approval(&self.agents.journal, draft)
}
fn commit(
&mut self,
draft: &ApprovedDraft,
approval: &ApprovalTransition,
) -> Result<Execution, DraftError> {
let bound = self.agents.journal.read(|snapshot| {
snapshot
.prepared
.values()
.any(|prepared| prepared.draft.as_deref() == Some(&draft.id))
})?;
if !bound {
return self.agents.commit(draft, approval);
}
self.target(draft)?.commit(draft, approval)
}
fn acknowledged(&self, id: &str) -> Result<bool, DraftError> {
if self.receipt_owner(id)? {
self.agents.acknowledged(id)
} else {
self.sites.acknowledged(id)
}
}
fn acknowledge(&mut self, id: &str, receipt: &Execution) -> Result<(), DraftError> {
if self.receipt_owner(id)? {
self.agents.acknowledge(id, receipt)
} else {
self.sites.acknowledge(id, receipt)
}
}
fn pending_acknowledgments(
&self,
limit: NonZeroUsize,
) -> Result<Vec<ApprovedDraft>, DraftError> {
let mut pending = self.agents.pending_acknowledgments(limit)?;
pending.extend(self.sites.pending_acknowledgments(limit)?);
if pending.len() > limit.get() {
return Err(DraftError::Bound);
}
Ok(pending)
}
fn deliver_outcome(
&mut self,
draft: &ApprovedDraft,
receipt: &Execution,
) -> Result<(), DraftError> {
if self.receipt_owner(&draft.id)? {
self.agents.deliver_outcome(draft, receipt)
} else {
self.sites.deliver_outcome(draft, receipt)
}
}
}