1use thiserror::Error;
4
5#[derive(Error, Debug)]
7pub enum GraphError {
8 #[error("No entry node defined")]
10 NoEntryNode,
11
12 #[error("Node not found: {0}")]
14 NodeNotFound(String),
15
16 #[error("Cycle detected in graph")]
18 CycleDetected,
19
20 #[error("Node '{node}' execution failed: {message}")]
22 ExecutionFailed {
23 node: String,
25 message: String,
27 },
28
29 #[error("Maximum steps exceeded: {0}")]
31 MaxStepsExceeded(u32),
32
33 #[error("Invalid graph: {0}")]
35 InvalidGraph(String),
36
37 #[error("Persistence error: {0}")]
39 Persistence(String),
40
41 #[error("Serialization error: {0}")]
43 Serialization(String),
44
45 #[error("{0}")]
47 Other(#[from] anyhow::Error),
48}
49
50impl GraphError {
51 pub fn node_not_found(name: impl Into<String>) -> Self {
53 Self::NodeNotFound(name.into())
54 }
55
56 pub fn execution_failed(node: impl Into<String>, message: impl Into<String>) -> Self {
58 Self::ExecutionFailed {
59 node: node.into(),
60 message: message.into(),
61 }
62 }
63
64 pub fn persistence(msg: impl Into<String>) -> Self {
66 Self::Persistence(msg.into())
67 }
68}
69
70pub type GraphResult<T> = Result<T, GraphError>;
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn test_error_display() {
79 let err = GraphError::node_not_found("test");
80 assert!(err.to_string().contains("test"));
81 }
82
83 #[test]
84 fn test_execution_failed() {
85 let err = GraphError::execution_failed("node1", "failed");
86 assert!(err.to_string().contains("node1"));
87 assert!(err.to_string().contains("failed"));
88 }
89}