stygian_graph/domain.rs
1//! Domain layer - core business logic
2//!
3//! Contains pure business logic with no infrastructure dependencies.
4//! Domain layer only imports from ports (trait definitions), never from adapters.
5
6/// DAG execution engine using petgraph
7pub mod graph;
8
9/// Pipeline types with typestate pattern
10pub mod pipeline;
11
12/// Worker pool executor with backpressure
13pub mod executor;
14
15/// Idempotency tracking system
16pub mod idempotency;
17
18/// API discovery types (response shape, pagination, field inference)
19pub mod discovery;
20
21/// Domain error types
22pub mod error {
23 use thiserror::Error;
24
25 /// Primary error type for the stygian-graph crate
26 ///
27 /// Encompasses all domain-level errors following hexagonal architecture principles.
28 ///
29 /// # Example
30 ///
31 /// ```
32 /// use stygian_graph::domain::error::{StygianError, GraphError};
33 ///
34 /// fn validate_pipeline() -> Result<(), StygianError> {
35 /// Err(StygianError::Graph(GraphError::CycleDetected))
36 /// }
37 /// ```
38 #[derive(Debug, Error)]
39 pub enum StygianError {
40 /// Graph execution errors
41 #[error("Graph error: {0}")]
42 Graph(#[from] GraphError),
43
44 /// Service interaction errors
45 #[error("Service error: {0}")]
46 Service(#[from] ServiceError),
47
48 /// AI provider errors
49 #[error("Provider error: {0}")]
50 Provider(#[from] ProviderError),
51
52 /// Configuration errors
53 #[error("Config error: {0}")]
54 Config(#[from] ConfigError),
55
56 /// Rate limiting errors
57 #[error("Rate limit error: {0}")]
58 RateLimit(#[from] RateLimitError),
59
60 /// Caching errors
61 #[error("Cache error: {0}")]
62 Cache(#[from] CacheError),
63 }
64
65 /// Graph-specific errors
66 #[derive(Debug, Error)]
67 pub enum GraphError {
68 /// Graph contains a cycle (DAG violation)
69 #[error("Graph contains cycle, cannot execute")]
70 CycleDetected,
71
72 /// Invalid node reference
73 #[error("Node not found: {0}")]
74 NodeNotFound(String),
75
76 /// Invalid edge configuration
77 #[error("Invalid edge: {0}")]
78 InvalidEdge(String),
79
80 /// Pipeline validation failed
81 #[error("Invalid pipeline: {0}")]
82 InvalidPipeline(String),
83
84 /// Execution failed
85 #[error("Execution failed: {0}")]
86 ExecutionFailed(String),
87 }
88
89 /// Service-level errors
90 #[derive(Debug, Error)]
91 pub enum ServiceError {
92 /// Service unavailable
93 #[error("Service unavailable: {0}")]
94 Unavailable(String),
95
96 /// Service timeout
97 #[error("Service timeout after {0}ms")]
98 Timeout(u64),
99
100 /// Service returned invalid response
101 #[error("Invalid response: {0}")]
102 InvalidResponse(String),
103
104 /// Service authentication failed
105 #[error("Authentication failed: {0}")]
106 AuthenticationFailed(String),
107
108 /// Service is rate-limiting; caller should retry after the given delay
109 #[error("Rate limited, retry after {retry_after_ms}ms")]
110 RateLimited {
111 /// Milliseconds to wait before retrying
112 retry_after_ms: u64,
113 },
114 }
115
116 /// AI provider errors
117 #[derive(Debug, Error)]
118 pub enum ProviderError {
119 /// Provider API error
120 #[error("API error: {0}")]
121 ApiError(String),
122
123 /// Invalid API key or credentials
124 #[error("Invalid credentials")]
125 InvalidCredentials,
126
127 /// Token limit exceeded
128 #[error("Token limit exceeded: {0}")]
129 TokenLimitExceeded(String),
130
131 /// Model not available
132 #[error("Model not available: {0}")]
133 ModelUnavailable(String),
134
135 /// Content policy violation
136 #[error("Content policy violation: {0}")]
137 ContentPolicyViolation(String),
138 }
139
140 /// Configuration errors
141 #[derive(Debug, Error)]
142 pub enum ConfigError {
143 /// Missing required configuration
144 #[error("Missing required config: {0}")]
145 MissingConfig(String),
146
147 /// Invalid configuration value
148 #[error("Invalid config value for '{key}': {reason}")]
149 InvalidValue {
150 /// Configuration key
151 key: String,
152 /// Reason for invalidity
153 reason: String,
154 },
155
156 /// Configuration file error
157 #[error("Config file error: {0}")]
158 FileError(String),
159
160 /// TOML parsing error
161 #[error("TOML parse error: {0}")]
162 ParseError(String),
163 }
164
165 /// Rate limiting errors
166 #[derive(Debug, Error)]
167 pub enum RateLimitError {
168 /// Rate limit exceeded
169 #[error("Rate limit exceeded: {0} requests per {1} seconds")]
170 Exceeded(u32, u32),
171
172 /// Quota exhausted
173 #[error("Quota exhausted: {0}")]
174 QuotaExhausted(String),
175
176 /// Retry after duration
177 #[error("Retry after {0} seconds")]
178 RetryAfter(u64),
179 }
180
181 /// Caching errors
182 #[derive(Debug, Error)]
183 pub enum CacheError {
184 /// Cache miss
185 #[error("Cache miss: {0}")]
186 Miss(String),
187
188 /// Cache write failed
189 #[error("Cache write failed: {0}")]
190 WriteFailed(String),
191
192 /// Cache read failed
193 #[error("Cache read failed: {0}")]
194 ReadFailed(String),
195
196 /// Cache eviction failed
197 #[error("Cache eviction failed: {0}")]
198 EvictionFailed(String),
199
200 /// Cache corrupted
201 #[error("Cache corrupted: {0}")]
202 Corrupted(String),
203 }
204
205 /// Domain result type using `StygianError`
206 pub type Result<T> = std::result::Result<T, StygianError>;
207
208 /// Legacy domain error (kept for backward compatibility)
209 #[derive(Debug, Error)]
210 pub enum DomainError {
211 /// Graph contains cycle
212 #[error("Graph contains cycle, cannot execute")]
213 CycleDetected,
214
215 /// Invalid pipeline configuration
216 #[error("Invalid pipeline: {0}")]
217 InvalidPipeline(String),
218
219 /// Execution failed
220 #[error("Execution failed: {0}")]
221 ExecutionFailed(String),
222
223 /// Service error
224 #[error("Service error: {0}")]
225 ServiceError(String),
226 }
227
228 /// Legacy domain result type
229 pub type DomainResult<T> = std::result::Result<T, DomainError>;
230}