aion/workloop/error.rs
1//! Typed errors for the workloop engine services.
2
3use aion_core::{WorkflowId, WorkloopSpecError};
4use aion_store::StoreError;
5
6use crate::durability::DurabilityError;
7
8/// Errors produced by the workloop services.
9#[derive(thiserror::Error, Debug)]
10pub enum WorkloopError {
11 /// A declaration was invalid at the engine boundary (no assumed defaults:
12 /// cadence, tolerance, and retention are declared or refused).
13 #[error("workloop declaration refused: {0}")]
14 Spec(#[from] WorkloopSpecError),
15
16 /// The workloop store refused or failed an operation.
17 #[error("workloop store failure: {0}")]
18 Store(#[from] StoreError),
19
20 /// The single-Recorder append path failed.
21 #[error("workloop record failure: {0}")]
22 Durability(#[from] DurabilityError),
23
24 /// A loop id was expected to be registered and was not.
25 #[error("workloop {loop_id} is not registered")]
26 NotRegistered {
27 /// The unregistered loop.
28 loop_id: WorkflowId,
29 },
30
31 /// A loop was already registered under this id.
32 #[error("workloop {loop_id} is already registered")]
33 AlreadyRegistered {
34 /// The already-registered loop.
35 loop_id: WorkflowId,
36 },
37
38 /// The sweep interval was zero: the sweeper's clock is a declared value,
39 /// never defaulted, and a zero interval is a busy-spin, not a cadence.
40 #[error("workloop sweep interval must be greater than zero")]
41 ZeroSweepInterval,
42
43 /// A declared duration could not be represented on the engine clock.
44 #[error("declared duration is not representable: {reason}")]
45 UnrepresentableDuration {
46 /// What overflowed.
47 reason: String,
48 },
49
50 /// A health sample named an invariant the loop never declared.
51 #[error("health sample names undeclared invariant `{invariant}` on loop {loop_id}")]
52 UndeclaredInvariant {
53 /// The loop the sample was fed to.
54 loop_id: WorkflowId,
55 /// The undeclared invariant name.
56 invariant: String,
57 },
58
59 /// The engine seam refused an operation (recording, waking, spawning).
60 #[error("engine seam failure: {reason}")]
61 Engine {
62 /// Human-readable seam failure reason.
63 reason: String,
64 },
65}
66
67impl From<WorkloopError> for crate::error::EngineError {
68 fn from(error: WorkloopError) -> Self {
69 Self::Runtime {
70 reason: error.to_string(),
71 }
72 }
73}