angee.workflows.steps
Step implementation seam for workflow definitions.
Step rows store a registry key in step_class. The configured class owns the behavior selected by that key and validates the row's config before the row is saved. Product addons register their own :class:StepImpl subclasses through ANGEE_WORKFLOW_STEP_CLASSES; row data never stores dotted import paths.
Implementations declare deterministic: deterministic implementations may be replayed for routing, while non-deterministic activity implementations are journaled by the runtime. Implementations may also declare decision_schema for typed resume payloads. Suspension persists no in-process state: resume_state on the future step-run journal is the only state surviving suspension, and an implementation must write any continuation facts there before returning a suspended result.
GATE_POLICIES
Seat aggregation policies supported by the built-in gate step.
TransientStepError
class TransientStepError(Exception)Signal that a step implementation failed with a retryable condition.
StepRetryPolicy
@dataclass(frozen=True, slots=True)
class StepRetryPolicy()Static queue retry policy declared by one step's JSON config.
DecisionSpec
@dataclass(frozen=True, slots=True)
class DecisionSpec()Declaration for one awaited decision slot created while a step suspends.
StepResult
@dataclass(frozen=True, slots=True)
class StepResult()Result returned by a workflow step implementation.
done(output, outcome) completes the step and routes by outcome. wait(until=...) records a durable timer wake. External events use :func:angee.workflows.engine.deliver, whose run-scoped generation prevents a delivery racing with this wait from being lost. suspend() pauses the step until an external resolution writes the next journal facts.
done
@classmethod
def done(cls, output: Any = None, outcome: str = "") -> SelfReturn a completed step result.
wait
@classmethod
def wait(cls,
*,
until: datetime | None = None,
resume_state: dict[str, Any] | None = None) -> SelfReturn a durable wait result.
suspend
@classmethod
def suspend(
cls,
*,
resume_state: dict[str, Any] | None = None,
decisions: list[DecisionSpec] | tuple[DecisionSpec, ...] = ()
) -> SelfReturn a suspended step result.
StepImpl
class StepImpl(ImplBase)Base class for registry-selected workflow step implementations.
validate_config
@classmethod
def validate_config(cls, config: Any) -> NoneValidate a step row's JSON config for this implementation.
run
def run(step_run: Any, *, now: datetime) -> StepResultExecute one step-run journal row.
heartbeat
def heartbeat(step_run: Any, *, at: datetime | None = None) -> NoneRefresh step_run's heartbeat while a long implementation is running.
retry_policy_from_config
def retry_policy_from_config(config: Any) -> StepRetryPolicyReturn the queue retry policy declared by config.
validate_retry_config
def validate_retry_config(config: Any) -> NoneValidate the common per-step retry block.
HandlerStep
class HandlerStep(StepImpl)Abstract activity step base registered as the built-in handler key.
WaitStep
class WaitStep(StepImpl)Built-in timer wait step.
validate_config
@classmethod
def validate_config(cls, config: Any) -> NoneValidate timer wait configuration.
run
def run(step_run: Any, *, now: datetime) -> StepResultReturn done once the timer or event condition has arrived.
GateStep
class GateStep(StepImpl)Built-in gate step that suspends until Slice 4 decision rows exist.
validate_config
@classmethod
def validate_config(cls, config: Any) -> NoneValidate declarative gate slot configuration.
run
def run(step_run: Any, *, now: datetime) -> StepResultSuspend the step, keeping only durable resume state.
MapStep
class MapStep(StepImpl)Built-in control step that maps one target step over a journaled item list.
validate_config
@classmethod
def validate_config(cls, config: Any) -> NoneValidate the map declaration consumed by the engine.
engine_expanded_filter
@classmethod
def engine_expanded_filter(cls) -> dict[str, Any]Return the ORM predicate for map parent rows the engine expands.
target_step
@classmethod
def target_step(cls, step_run: Any) -> AnyReturn the configured target step for one map parent row.
items
@classmethod
def items(cls, step_run: Any) -> list[Any]Return the item list resolved from this map step's config.
policy_passes
@classmethod
def policy_passes(cls, config: Any, output: Mapping[str, Any]) -> boolReturn whether aggregate map output satisfies config.
config_mapping
@classmethod
def config_mapping(cls, step_run: Any) -> Mapping[str, Any]Return the map config as a mapping.
expression_value
@classmethod
def expression_value(cls, expression: Any, step_run: Any) -> AnyResolve a map items expression against subject, run, or input.
lookup
@staticmethod
def lookup(value: Any, key: str) -> AnyRead one expression path segment from a mapping or object.
positive_int
def positive_int(value: Any, label: str) -> intReturn value as a positive integer or raise a config error.
non_negative_int
def non_negative_int(value: Any, label: str) -> intReturn value as a non-negative integer or raise a config error.
optional_number
def optional_number(value: Any, label: str) -> float | NoneReturn value as a number when present, or raise a config error.
optional_positive_int
def optional_positive_int(value: Any) -> int | NoneLeniently return value as a positive integer when possible.
optional_non_negative_int
def optional_non_negative_int(value: Any) -> int | NoneLeniently return value as a non-negative integer when possible.