use std::fmt::Display;
use thiserror::Error;
#[derive(Error, Debug, Clone)]
pub enum FlowrsError {
#[error("Node execution error: {0}")]
NodeExecution(String),
#[error("Workflow execution error: {0}")]
WorkflowExecution(String),
#[error("Node not found: {0}")]
NodeNotFound(String),
#[error("No transition defined for action: {0}")]
NoTransitionDefined(String),
#[error("Serialization error: {0}")]
SerializationError(String),
#[error("Deserialization error: {0}")]
DeserializationError(String),
#[error("Task join error: {0}")]
JoinError(String),
#[error("Cycle detected in workflow execution")]
WorkflowCycleDetected,
#[error("Workflow definition error: {0}")]
WorkflowDefinitionError(String),
#[error("Batch processing error: {0}")]
BatchProcessingError(String),
#[error("Unexpected node outcome: {0}")]
UnexpectedOutcome(String),
#[error("{0}")]
Other(String),
}
pub type FlowrsResult<T> = Result<T, FlowrsError>;
impl FlowrsError {
pub fn node_execution(node_id: impl Display, message: impl Display) -> Self {
Self::NodeExecution(format!("Node {}: {}", node_id, message))
}
pub fn batch_processing(
message: impl Display,
source: Box<dyn std::error::Error + Send + Sync>,
) -> Self {
Self::BatchProcessingError(format!("{}: {}", message, source))
}
pub fn unexpected_outcome(message: impl Display) -> Self {
Self::UnexpectedOutcome(message.to_string())
}
pub fn node_not_found(node_id: impl Display) -> Self {
Self::NodeNotFound(node_id.to_string())
}
pub fn timeout(message: impl Display) -> Self {
Self::Other(format!("Timeout: {}", message))
}
pub fn is_timeout(&self) -> bool {
match self {
Self::Other(msg) => msg.starts_with("Timeout:"),
_ => false,
}
}
}