#![allow(clippy::type_complexity)]
use crate::{AggregateRoot, AppendError, AppendResult, ExpectedRevision, TransactionalOutbox};
#[derive(Debug, PartialEq, Eq)]
pub enum TransactionalOutboxOperationError<E> {
Adapter(AppendError<E>),
AlreadyEnqueued,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TransactionalOutboxCompletionError {
MissingEnqueue,
EnqueueFailedConsumed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum OperationState {
Pending,
Succeeded,
FailedConsumed,
}
pub struct TransactionalOutboxLifecycleContext<'a, A, O>
where
A: AggregateRoot,
O: TransactionalOutbox<Aggregate = A>,
{
aggregate: &'a mut A,
outbox: &'a mut O,
expected: ExpectedRevision,
state: OperationState,
}
impl<'a, A, O> TransactionalOutboxLifecycleContext<'a, A, O>
where
A: AggregateRoot,
O: TransactionalOutbox<Aggregate = A>,
{
pub fn new(aggregate: &'a mut A, outbox: &'a mut O, expected: ExpectedRevision) -> Self {
Self {
aggregate,
outbox,
expected,
state: OperationState::Pending,
}
}
pub fn save_and_enqueue(
&mut self,
) -> Result<AppendResult, TransactionalOutboxOperationError<O::Error>> {
if self.state != OperationState::Pending {
return Err(TransactionalOutboxOperationError::AlreadyEnqueued);
}
self.state = OperationState::FailedConsumed;
let events = self.aggregate.pull_events();
match self
.outbox
.save_and_enqueue(self.aggregate, self.expected, events)
{
Ok(result) => {
self.state = OperationState::Succeeded;
Ok(result)
}
Err(error) => Err(TransactionalOutboxOperationError::Adapter(error)),
}
}
pub fn complete(self) -> Result<(), TransactionalOutboxCompletionError> {
match self.state {
OperationState::Succeeded => Ok(()),
OperationState::Pending => Err(TransactionalOutboxCompletionError::MissingEnqueue),
OperationState::FailedConsumed => {
Err(TransactionalOutboxCompletionError::EnqueueFailedConsumed)
}
}
}
}
pub type OutboxLifecycleContext<'a, A, O> = TransactionalOutboxLifecycleContext<'a, A, O>;
pub type OutboxLifecycleOperationError<E> = TransactionalOutboxOperationError<E>;
pub type OutboxLifecycleCompletionError = TransactionalOutboxCompletionError;