//// Typed error taxonomy for Aion workflow authors. //// //// The `aion_flow` package models failure as data. Public fallible functions //// return typed `Result` errors; library code must not panic, call `todo`, or //// use assertions as control flow. Activity failures, decode failures, engine //// lifecycle failures, non-determinism, and unknown live-interaction names are //// all represented by the types in this module. import aion/codec /// An activity dispatch failure returned through `workflow.run`. /// /// `Retryable` and `Terminal` are the Gleam mirror of aion-core's retryable / /// terminal activity-error classification (aion-core C21). The engine retries /// `Retryable` failures according to the activity's explicit `RetryPolicy` until /// its attempts are exhausted, and fails immediately for `Terminal` failures. /// /// Engine-originated failures that can occur while dispatching or decoding an /// activity result are also represented here so `workflow.run(Activity(i, o))` /// remains a single typed `Result(o, ActivityError)` boundary. Decode failures /// preserve the typed codec error and are never swallowed or raised as panics. /// /// `details` carries structured detail data encoded by the author-facing codec /// layer. The SDK keeps it as an opaque string here so activity authors do not /// depend on engine payload internals. pub type ActivityError { Retryable(message: String, details: String) Terminal(message: String, details: String) ActivityDecodeFailed(codec.DecodeError) ActivityTimedOut(TimeoutError) ActivityCancelled(CancellationError) ActivityNonDeterministic(NonDeterminismError) ActivityEngineFailure(message: String) } /// Construct a retryable activity failure with no detail payload. pub fn retryable(message: String) -> ActivityError { Retryable(message: message, details: "") } /// Construct a retryable activity failure with an encoded detail payload. pub fn retryable_with_details( message: String, details: String, ) -> ActivityError { Retryable(message: message, details: details) } /// Construct a terminal activity failure with no detail payload. pub fn terminal(message: String) -> ActivityError { Terminal(message: message, details: "") } /// Construct a terminal activity failure with an encoded detail payload. pub fn terminal_with_details( message: String, details: String, ) -> ActivityError { Terminal(message: message, details: details) } /// A timeout reported by the engine lifecycle. /// /// Later workflow primitives such as `with_timeout`, timers, and activity /// timeout handling use this type when the engine decides that a deadline has /// expired. This is separate from author retry/terminal decisions because /// authors must not classify an engine timeout as an activity retry decision. pub type TimeoutError { TimedOut(message: String) } /// A cancellation reported by the engine lifecycle. /// /// Cancellation originates from the engine's workflow or command lifecycle and /// remains separate from author-returned activity decisions. pub type CancellationError { Cancelled(reason: String) } /// A deterministic replay violation reported by AD. /// /// This corresponds to AD's `NonDeterminismError`: the workflow command stream /// produced during replay did not match recorded history. Workflow code handles /// it as an engine-originated failure, never as an author retry/terminal /// decision. pub type NonDeterminismError { NonDeterminismViolation(message: String) } /// A generic engine-originated primitive failure. /// /// Deterministic primitives such as `workflow.now` and `workflow.random` are /// bound to AD through the FFI layer. If the engine reports an unavailable /// context or malformed deterministic value, the SDK returns this data rather /// than panicking. pub type EngineError { EngineFailure(message: String) } /// A workflow lifecycle primitive failure. pub type WorkflowError { WorkflowEngineFailure(message: String) } /// A boundary decode failure for workflow primitives. /// /// The wrapped `codec.DecodeError` preserves the typed decode reason and path /// produced by AF-002 codecs. Decode failures are returned as data and are never /// swallowed or raised as panics. pub type BoundaryDecodeError { DecodeFailed(codec.DecodeError) } /// A signal receive failure. /// /// Future signal primitives use this type to distinguish malformed payloads, /// unknown signal names, cancellation, and deterministic replay violations. pub type ReceiveError { ReceiveDecodeFailed(codec.DecodeError) UnknownSignal(name: String) ReceiveCancelled(CancellationError) ReceiveNonDeterministic(NonDeterminismError) ReceiveEngineFailure(message: String) } /// A query failure. /// /// The variants mirror the engine's query error taxonomy (AT-007 + the /// query-execution brief): `UnknownQuery` for an unregistered name, /// `QueryTimedOut` for an expired reply deadline, `QueryNotRunning` when the /// target workflow is terminal or non-resident (queries never resume a /// workflow solely to answer), and `QueryHandlerFailed` when the registered /// handler ran and reported an application-level failure (the `query_failed` /// wire code). Queries do not record workflow events. pub type QueryError { QueryDecodeFailed(codec.DecodeError) UnknownQuery(name: String) QueryTimedOut(TimeoutError) QueryNotRunning(workflow_id: String) QueryHandlerFailed(message: String) QueryEngineFailure(message: String) } /// A child-workflow await failure. /// /// A completed child returns `Ok(output)`. A child workflow failure returns /// `ChildWorkflowFailed(workflow_error)`, preserving the child workflow's typed /// error — engine-side child cancellation/timeout terminals arrive on this /// same path as failure data (the engine maps them to `ChildWorkflowFailed` /// history events with `cancelled:`/`timed_out:` message prefixes). Decode and /// engine failures are separate typed variants so boundary failures are never /// swallowed or raised as panics. pub type ChildError(workflow_error) { ChildWorkflowFailed(workflow_error) ChildOutputDecodeFailed(codec.DecodeError) ChildErrorDecodeFailed(codec.DecodeError) ChildEngineFailure(message: String) } /// A timeout wrapper for primitives that can either finish or expire. /// /// `TimedOutError` is reserved for genuine deadline expirations; an engine /// fault while establishing or settling the timeout scope surfaces as /// `TimeoutEngineFailure` so callers never mistake an infrastructure error /// for a timeout. pub type TimeoutResultError(error) { TimedOutError(TimeoutError) InnerError(error) TimeoutEngineFailure(message: String) }