use std::fmt;
use turnframe_core::case::CaseRef;
use turnframe_core::ids::{AccountId, UserId};
use turnframe_core::turn::ActorContext;
use super::{BatchOf, ExecutorFactory, SeedOf, SeededCase};
use crate::workflows::{InMemoryExecutor, PureWorkflow};
pub const CONFORMANCE_ACCOUNT: &str = "turnframe-executor-conformance";
pub const CONFORMANCE_USER: &str = "conformance-user";
pub struct InMemoryCase<W: PureWorkflow> {
account: AccountId,
user: UserId,
case_ref: CaseRef,
seed_state: Option<W::State>,
first: W::Command,
second: W::Command,
refused: W::Command,
}
impl<W: PureWorkflow> InMemoryCase<W> {
#[must_use]
pub fn new(
case_ref: CaseRef,
seed_state: Option<W::State>,
first: W::Command,
second: W::Command,
refused: W::Command,
) -> Self {
Self {
account: AccountId::from(CONFORMANCE_ACCOUNT),
user: UserId::from(CONFORMANCE_USER),
case_ref,
seed_state,
first,
second,
refused,
}
}
#[must_use]
pub fn with_actor(mut self, account: impl Into<AccountId>, user: impl Into<UserId>) -> Self {
self.account = account.into();
self.user = user.into();
self
}
#[must_use]
pub const fn case_ref(&self) -> &CaseRef {
&self.case_ref
}
}
impl<W: PureWorkflow> fmt::Debug for InMemoryCase<W> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("InMemoryCase")
.field("account", &self.account)
.field("case_ref", &self.case_ref)
.field("seeded", &self.seed_state.is_some())
.finish_non_exhaustive()
}
}
#[async_trait::async_trait]
impl<W> ExecutorFactory for InMemoryCase<W>
where
W: PureWorkflow + Default,
{
type Workflow = W;
type Executor = InMemoryExecutor<W>;
async fn seed(&self) -> Result<SeedOf<Self>, String> {
let executor = InMemoryExecutor::<W>::default();
if let Some(state) = self.seed_state.clone() {
executor.seed(
&self.account,
&self.case_ref.case_id,
state,
self.case_ref.expected_revision,
);
}
Ok(SeededCase::new(
executor,
ActorContext::new(self.account.clone(), self.user.clone()),
self.case_ref.clone(),
self.first.clone(),
self.second.clone(),
self.refused.clone(),
))
}
async fn interrupt_after(
&self,
seeded: &SeedOf<Self>,
batch: &BatchOf<Self>,
applied: usize,
) -> Result<(), String> {
seeded
.executor
.execute_prefix(batch, applied)
.map(|_| ())
.map_err(|error| format!("{error:?}"))
}
}