rustate 0.3.0

A Rust library for creating and managing state machines, inspired by XState.
Documentation
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Display};
use std::hash::Hash;
use thiserror::Error;
use tracing::error;

/// Errors that can occur during actor processing.
///
/// This enum defines the possible failure states an actor might encounter
/// while receiving or processing events.
#[derive(Error, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ActorError {
    /// Indicates a failure during the processing of a message.
    /// Contains a descriptive string of the error.
    #[error("Failed to process message: {0}")]
    ProcessingFailed(String),

    /// Indicates that an event of an unexpected type was received.
    /// This might happen if the actor's logic doesn't handle a specific event variant.
    #[error("Received unexpected event type")]
    UnexpectedEvent,

    /// Indicates that the actor has stopped or terminated.
    /// Further interaction with a stopped actor might result in this error.
    #[error("Actor has stopped")]
    Stopped,
    // TODO: Add more specific error cases as needed (e.g., Timeout, InvalidState).
}

/// The core trait that all actors must implement.
///
/// Actors encapsulate state and behavior, responding to incoming events
/// to update their state and potentially produce outputs.
/// This trait defines the fundamental structure and lifecycle of an actor.
#[async_trait]
pub trait Actor: Send + Sync + 'static {
    /// The type of the state managed by the actor.
    type State: Send + Sync + Clone + Debug + Serialize + for<'de> Deserialize<'de>;
    /// The type of context data used by the actor.
    type Context: Send + Sync + Clone + Default + Debug + Serialize + for<'de> Deserialize<'de>;
    /// The type of events the actor can handle.
    type Event: Send + Sync + Debug + Serialize + for<'de> Deserialize<'de>;
    /// The type used for state identifiers.
    type StateId: Send + Sync + Clone + Hash + Eq + Debug + Display;
    /// The output type produced by the actor upon reaching a final state.
    type Output: Send + Sync + Clone + Debug + Serialize + for<'de> Deserialize<'de>;

    /// Returns the initial state of the actor when it is first created.
    ///
    /// This function is called once during the actor's initialization phase.
    fn initial_state(&self) -> Self::State;

    /// Processes a received event and updates the actor's state accordingly.
    ///
    /// This method contains the core logic of the actor. It takes the current
    /// state and an incoming event, performs necessary computations or side effects,
    /// and returns the resulting new state or an error if processing fails.
    ///
    /// # Arguments
    ///
    /// * `state` - The current state of the actor.
    /// * `event` - The event received by the actor.
    ///
    /// # Returns
    ///
    /// A `Result` containing either the new state (`Ok(Self::State)`) after processing
    /// the event, or an `ActorError` (`Err(ActorError)`) if an error occurred.
    /// If the state does not change, the current state should be returned within the `Ok` variant.
    async fn receive(
        &self,
        state: Self::State,
        event: Self::Event,
    ) -> Result<Self::State, ActorError>;

    // Potential future additions:
    // - Lifecycle methods: `pre_start`, `post_stop`, `pre_restart`, `post_restart`
    // - Output computation: `compute_output(&self, old_state: &Self::State, new_state: &Self::State) -> Option<Self::Output>`
    // - Supervision strategies
}