use thiserror::Error;
#[derive(Error, Debug)]
pub enum GraphError {
#[error("No entry node defined")]
NoEntryNode,
#[error("Node not found: {0}")]
NodeNotFound(String),
#[error("Cycle detected in graph")]
CycleDetected,
#[error("Node '{node}' execution failed: {message}")]
ExecutionFailed {
node: String,
message: String,
},
#[error("Maximum steps exceeded: {0}")]
MaxStepsExceeded(u32),
#[error("Invalid graph: {0}")]
InvalidGraph(String),
#[error("Persistence error: {0}")]
Persistence(String),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("{0}")]
Other(#[from] anyhow::Error),
}
impl GraphError {
pub fn node_not_found(name: impl Into<String>) -> Self {
Self::NodeNotFound(name.into())
}
pub fn execution_failed(node: impl Into<String>, message: impl Into<String>) -> Self {
Self::ExecutionFailed {
node: node.into(),
message: message.into(),
}
}
pub fn persistence(msg: impl Into<String>) -> Self {
Self::Persistence(msg.into())
}
}
pub type GraphResult<T> = Result<T, GraphError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = GraphError::node_not_found("test");
assert!(err.to_string().contains("test"));
}
#[test]
fn test_execution_failed() {
let err = GraphError::execution_failed("node1", "failed");
assert!(err.to_string().contains("node1"));
assert!(err.to_string().contains("failed"));
}
}