buntrail-core 0.1.1

Revisioned documents and shared editor contracts.
Documentation
use crate::contracts::*;
pub struct OperationStateMachine {
    state: OperationState,
}
impl Default for OperationStateMachine {
    fn default() -> Self {
        Self::new()
    }
}
impl OperationStateMachine {
    pub fn new() -> Self {
        Self {
            state: OperationState::Accepted,
        }
    }
    pub fn state(&self) -> &OperationState {
        &self.state
    }
    pub fn transition(&mut self, event: OperationEvent) -> Result<OperationState, CoreError> {
        let next = match (&self.state, event) {
            (OperationState::Accepted, OperationEvent::Started) => OperationState::Running,
            (
                OperationState::Accepted | OperationState::Running,
                OperationEvent::Confirmed(result),
            ) => OperationState::Confirmed(result),
            (
                OperationState::Accepted | OperationState::Running,
                OperationEvent::Failed(failure),
            ) => match failure.effect {
                FailureEffect::ProvenNoEffect => OperationState::Failed(failure),
                FailureEffect::PossiblePartialEffects => {
                    OperationState::Unknown(ReconciliationEvidence {
                        target: failure.target,
                        observed: failure.observed,
                        explanation: failure.error.message,
                    })
                }
            },
            (
                OperationState::Accepted | OperationState::Running | OperationState::Unknown(_),
                OperationEvent::LostAcknowledgement(evidence),
            ) => OperationState::Unknown(evidence),
            (OperationState::Unknown(_), OperationEvent::Reconciled(result)) => {
                OperationState::Confirmed(result)
            }
            _ => {
                return Err(CoreError::new(
                    ErrorCode::InvalidTransition,
                    "operation requires evidence; replay is forbidden",
                ));
            }
        };
        self.state = next;
        Ok(self.state.clone())
    }
}