1use crate::node::*;
2use std::collections::HashMap;
3use anyhow::Result;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7pub enum WorkerError {
8  #[error("Worker Not Found: `{0}`")]
9  WorkerNotFound(String),
10  #[error("Node[{0}]: {1}")]
11  NodeRunError(i64, anyhow::Error)
12}
13
14pub trait Worker {
15  fn name(&self) -> &str;
16  fn work(&self, node: &Node, input_data: InputData) -> Result<OutputData>;
17}
18
19pub struct Workers(HashMap<String, Box<dyn Worker>>);
20
21impl Workers {
22  pub fn call(&self, name: &str, node: &Node, input: InputData) -> Result<OutputData> {
23    self.0.get(name)
24      .map(|worker| 
25        worker.work(&node, input)
26          .map_err(|e| 
27            anyhow!(WorkerError::NodeRunError(node.id, e))
28          )
29        )
30        .ok_or(WorkerError::WorkerNotFound(name.into()))?
31  }
32}
33
34pub struct WorkersBuilder {
35  data: Vec<(String, Box<dyn Worker>)>
36}
37
38#[allow(dead_code)]
39impl WorkersBuilder {
40  pub fn new() -> WorkersBuilder {
41    WorkersBuilder { data: vec![] }
42  }
43
44  pub fn add<A>(&mut self, worker: A) -> &mut Self where A: Worker + 'static {
45    self.data.push((worker.name().to_string(), Box::new(worker)));
46    self
47  }
48
49  pub fn build(self) -> Workers {
50    Workers(self.data.into_iter().collect::<HashMap<_,_>>())
51  }
52}