1use reifydb_core::error::diagnostic::flow::{
5 flow_coordinator_busy, flow_coordinator_stopped, flow_ffi_unsupported_on_wasm, flow_invalid_worker_id,
6 flow_missing_input_edge, flow_node_input_arity, flow_parent_operator_not_found, flow_pool_actor_stopped,
7 flow_pool_busy, flow_sink_dictionary_not_found, flow_sink_missing_system_column,
8 flow_sink_view_not_visible_at_registration, flow_state_decode_failed, flow_state_encode_failed,
9 flow_transaction_dictionary_write_divergence, flow_transaction_keyspace_overlap, flow_unknown_diff_origin,
10 flow_unknown_operator, flow_unsupported_node, flow_worker_failed, flow_worker_stopped, native_abi_tag_mismatch,
11 native_create_failed, native_library_not_loaded, native_operator_not_found, native_symbol_not_found,
12};
13use reifydb_value::error::{Diagnostic, Error, IntoDiagnostic};
14
15#[derive(Debug, thiserror::Error)]
16pub enum FlowDispatchError {
17 #[error("invalid flow worker id {worker_id} (pool has {num_workers} workers)")]
18 InvalidWorkerId {
19 worker_id: usize,
20 num_workers: usize,
21 },
22
23 #[error("flow worker {worker_id} has stopped")]
24 WorkerStopped {
25 worker_id: usize,
26 },
27
28 #[error("flow pool is busy")]
29 PoolBusy,
30
31 #[error("flow coordinator is busy")]
32 CoordinatorBusy,
33
34 #[error("flow coordinator actor has stopped")]
35 CoordinatorStopped,
36
37 #[error("flow pool actor has stopped")]
38 PoolActorStopped,
39
40 #[error("flow transaction keyspace overlap: {key}")]
41 KeyspaceOverlap {
42 key: String,
43 },
44
45 #[error("dictionary write divergence on key {key}")]
46 DictionaryWriteDivergence {
47 key: String,
48 },
49
50 #[error("flow worker {worker_id} failed")]
51 WorkerFailed {
52 worker_id: usize,
53 cause: Error,
54 },
55}
56
57impl IntoDiagnostic for FlowDispatchError {
58 fn into_diagnostic(self) -> Diagnostic {
59 match self {
60 FlowDispatchError::InvalidWorkerId {
61 worker_id,
62 num_workers,
63 } => flow_invalid_worker_id(worker_id, num_workers),
64 FlowDispatchError::WorkerStopped {
65 worker_id,
66 } => flow_worker_stopped(worker_id),
67 FlowDispatchError::PoolBusy => flow_pool_busy(),
68 FlowDispatchError::CoordinatorBusy => flow_coordinator_busy(),
69 FlowDispatchError::CoordinatorStopped => flow_coordinator_stopped(),
70 FlowDispatchError::PoolActorStopped => flow_pool_actor_stopped(),
71 FlowDispatchError::KeyspaceOverlap {
72 key,
73 } => flow_transaction_keyspace_overlap(key),
74 FlowDispatchError::DictionaryWriteDivergence {
75 key,
76 } => flow_transaction_dictionary_write_divergence(key),
77 FlowDispatchError::WorkerFailed {
78 worker_id,
79 cause,
80 } => flow_worker_failed(worker_id, *cause.0),
81 }
82 }
83}
84
85impl From<FlowDispatchError> for Error {
86 fn from(err: FlowDispatchError) -> Self {
87 Error(Box::new(err.into_diagnostic()))
88 }
89}
90
91#[derive(Debug, thiserror::Error)]
92pub enum FlowStateError {
93 #[error("failed to serialize flow operator state '{state}': {cause}")]
94 Encode {
95 state: &'static str,
96 cause: String,
97 },
98
99 #[error("failed to deserialize flow operator state '{state}': {cause}")]
100 Decode {
101 state: &'static str,
102 cause: String,
103 },
104}
105
106impl IntoDiagnostic for FlowStateError {
107 fn into_diagnostic(self) -> Diagnostic {
108 match self {
109 FlowStateError::Encode {
110 state,
111 cause,
112 } => flow_state_encode_failed(state, cause),
113 FlowStateError::Decode {
114 state,
115 cause,
116 } => flow_state_decode_failed(state, cause),
117 }
118 }
119}
120
121impl From<FlowStateError> for Error {
122 fn from(err: FlowStateError) -> Self {
123 Error(Box::new(err.into_diagnostic()))
124 }
125}
126
127#[derive(Debug, thiserror::Error)]
128pub enum FlowGraphError {
129 #[error("flow node kind '{kind}' is not supported in persistent flows")]
130 UnsupportedNode {
131 kind: &'static str,
132 },
133
134 #[error("flow node '{node}' requires {expected} inputs, but the DAG provided {found}")]
135 NodeInputArity {
136 node: &'static str,
137 expected: &'static str,
138 found: usize,
139 },
140
141 #[error("parent operator not found while wiring flow node input: {input}")]
142 ParentOperatorNotFound {
143 input: String,
144 },
145
146 #[error("unknown flow operator '{operator}'")]
147 UnknownOperator {
148 operator: String,
149 },
150
151 #[error("FFI operators are not supported on the wasm target")]
152 FfiUnsupportedOnWasm,
153
154 #[error("flow node is missing a required input edge")]
155 MissingInputEdge,
156
157 #[error("{operator} operator received a diff from an unknown node")]
158 UnknownDiffOrigin {
159 operator: &'static str,
160 origin: Option<String>,
161 },
162
163 #[error("transactional flow {flow_id} references sink view {view_id} not visible at registration")]
164 SinkViewNotVisibleAtRegistration {
165 flow_id: u64,
166 view_id: u64,
167 },
168}
169
170impl IntoDiagnostic for FlowGraphError {
171 fn into_diagnostic(self) -> Diagnostic {
172 match self {
173 FlowGraphError::UnsupportedNode {
174 kind,
175 } => flow_unsupported_node(kind),
176 FlowGraphError::NodeInputArity {
177 node,
178 expected,
179 found,
180 } => flow_node_input_arity(node, expected, found),
181 FlowGraphError::ParentOperatorNotFound {
182 input,
183 } => flow_parent_operator_not_found(input),
184 FlowGraphError::UnknownOperator {
185 operator,
186 } => flow_unknown_operator(&operator),
187 FlowGraphError::FfiUnsupportedOnWasm => flow_ffi_unsupported_on_wasm(),
188 FlowGraphError::MissingInputEdge => flow_missing_input_edge(),
189 FlowGraphError::UnknownDiffOrigin {
190 operator,
191 origin,
192 } => flow_unknown_diff_origin(operator, origin),
193 FlowGraphError::SinkViewNotVisibleAtRegistration {
194 flow_id,
195 view_id,
196 } => flow_sink_view_not_visible_at_registration(flow_id, view_id),
197 }
198 }
199}
200
201impl From<FlowGraphError> for Error {
202 fn from(err: FlowGraphError) -> Self {
203 Error(Box::new(err.into_diagnostic()))
204 }
205}
206
207#[derive(Debug, thiserror::Error)]
208pub enum NativeOperatorError {
209 #[error("native operator ABI tag mismatch: plugin {plugin:#06x}, host {host:#06x}")]
210 AbiTagMismatch {
211 plugin: u32,
212 host: u32,
213 },
214
215 #[error("native operator library not loaded: {path}")]
216 LibraryNotLoaded {
217 path: String,
218 },
219
220 #[error("native operator symbol '{symbol}' not found: {cause}")]
221 SymbolNotFound {
222 symbol: &'static str,
223 cause: String,
224 },
225
226 #[error("native operator '{operator}' not found")]
227 OperatorNotFound {
228 operator: String,
229 },
230
231 #[error("failed to create native/FFI operator: {cause}")]
232 CreateFailed {
233 cause: String,
234 },
235}
236
237impl IntoDiagnostic for NativeOperatorError {
238 fn into_diagnostic(self) -> Diagnostic {
239 match self {
240 NativeOperatorError::AbiTagMismatch {
241 plugin,
242 host,
243 } => native_abi_tag_mismatch(plugin, host),
244 NativeOperatorError::LibraryNotLoaded {
245 path,
246 } => native_library_not_loaded(&path),
247 NativeOperatorError::SymbolNotFound {
248 symbol,
249 cause,
250 } => native_symbol_not_found(symbol, cause),
251 NativeOperatorError::OperatorNotFound {
252 operator,
253 } => native_operator_not_found(&operator),
254 NativeOperatorError::CreateFailed {
255 cause,
256 } => native_create_failed(cause),
257 }
258 }
259}
260
261impl From<NativeOperatorError> for Error {
262 fn from(err: NativeOperatorError) -> Self {
263 Error(Box::new(err.into_diagnostic()))
264 }
265}
266
267#[derive(Debug, thiserror::Error)]
268pub enum FlowSinkError {
269 #[error("row at index {row_idx} is missing the '{column}' system column")]
270 MissingSystemColumn {
271 column: &'static str,
272 row_idx: usize,
273 },
274
275 #[error("dictionary {dictionary_id} not found for view column '{column}'")]
276 DictionaryNotFound {
277 dictionary_id: String,
278 column: String,
279 },
280}
281
282impl IntoDiagnostic for FlowSinkError {
283 fn into_diagnostic(self) -> Diagnostic {
284 match self {
285 FlowSinkError::MissingSystemColumn {
286 column,
287 row_idx,
288 } => flow_sink_missing_system_column(column, row_idx),
289 FlowSinkError::DictionaryNotFound {
290 dictionary_id,
291 column,
292 } => flow_sink_dictionary_not_found(dictionary_id, &column),
293 }
294 }
295}
296
297impl From<FlowSinkError> for Error {
298 fn from(err: FlowSinkError) -> Self {
299 Error(Box::new(err.into_diagnostic()))
300 }
301}