//! The `Saga` trait — what a user implements to define a saga.

use serde::Serialize;
use serde::de::DeserializeOwned;

use crate::builder::SagaBuilder;

/// A saga: a typed name plus a topology of step handlers, built by
/// [`Saga::build`]. The framework owns the durability layer (see
/// [`crate::envelope::SagaEnvelope`]); the user only declares the shape.
pub trait Saga: Sized + Send + Sync + 'static {
    /// The state struct carried by each instance. Accumulated at start (from
    /// the trigger event) and never mutated again by user code — step
    /// handlers see it through `State<_>` read-only.
    type State: Default + Clone + Serialize + DeserializeOwned + Send + Sync + 'static;

    /// Stable name. Used as the lease key, the envelope's stream category
    /// suffix, and the prefix for instance stream ids.
    fn name() -> &'static str;

    /// Declare the saga's topology. Called once per registration.
    fn build(builder: SagaBuilder<Self>) -> SagaBuilder<Self>;
}

/// Returned from a `start_on` correlator: how to start a fresh instance from a
/// triggering domain event.
pub struct Start<S: Saga> {
    pub instance_id: String,
    pub state: S::State,
}
