use aion_core::{SearchAttributeError, WorkflowId};
use aion_store::StoreError;
#[derive(thiserror::Error, Clone, Debug, PartialEq, Eq)]
#[error(
"non-determinism in workflow {workflow_id} at sequence {seq}: expected {expected}, found {found}"
)]
pub struct NonDeterminismError {
pub workflow_id: WorkflowId,
pub seq: u64,
pub expected: String,
pub found: String,
}
#[derive(thiserror::Error, Debug)]
pub enum DurabilityError {
#[error("store error: {0}")]
Store(#[from] StoreError),
#[error("non-determinism violation: {0}")]
NonDeterminism(#[from] NonDeterminismError),
#[error("history shape error: {reason}")]
HistoryShape {
reason: String,
},
#[error("search attribute validation error: {0}")]
SearchAttribute(#[from] SearchAttributeError),
}
#[cfg(test)]
mod tests {
use super::{DurabilityError, NonDeterminismError};
use aion_core::WorkflowId;
use aion_store::StoreError;
fn non_determinism_error() -> NonDeterminismError {
NonDeterminismError {
workflow_id: WorkflowId::new(uuid::Uuid::nil()),
seq: 42,
expected: "activity schedule ordinal 7".to_owned(),
found: "timer fired timer:named:deadline".to_owned(),
}
}
#[test]
fn non_determinism_display_includes_context() {
let error = non_determinism_error();
let message = error.to_string();
assert!(message.contains("00000000-0000-0000-0000-000000000000"));
assert!(message.contains("42"));
assert!(message.contains("activity schedule ordinal 7"));
assert!(message.contains("timer fired timer:named:deadline"));
}
#[test]
fn durability_error_display_mentions_underlying_cause() {
let store = DurabilityError::Store(StoreError::SequenceConflict {
expected: 10,
found: 11,
});
let non_determinism = DurabilityError::NonDeterminism(non_determinism_error());
let history_shape = DurabilityError::HistoryShape {
reason: "activity result without preceding schedule".to_owned(),
};
let store_message = store.to_string();
let non_determinism_message = non_determinism.to_string();
let history_shape_message = history_shape.to_string();
assert!(!store_message.is_empty());
assert!(store_message.contains("sequence conflict"));
assert!(!non_determinism_message.is_empty());
assert!(non_determinism_message.contains("activity schedule ordinal 7"));
assert!(non_determinism_message.contains("timer fired timer:named:deadline"));
assert!(!history_shape_message.is_empty());
assert!(history_shape_message.contains("activity result without preceding schedule"));
}
}