chord_output/report/
mod.rs1use std::borrow::Borrow;
2use std::sync::Arc;
3
4use async_trait::async_trait;
5
6use chord_core::flow::Flow;
7use chord_core::output::{Error, JobReporter, TaskReporter};
8use chord_core::task::TaskId;
9use chord_core::value::Value;
10use ReportError::*;
11
12#[cfg(feature = "report_csv")]
13mod csv;
14#[derive(thiserror::Error, Debug)]
18enum ReportError {
19 #[error("conf lost")]
20 ConfLost,
21
22 #[error("invalid {0}: {1}")]
23 ConfInvalid(String, String),
24
25 #[error("conf lost entry `{0}`")]
26 ConfLostEntry(String),
27}
28
29pub struct DefaultJobReporter {
30 delegate: Box<dyn JobReporter>,
31}
32
33impl DefaultJobReporter {
34 pub async fn new(
35 conf: Option<&Value>,
36 name: &str,
37 exec_id: &str,
38 ) -> Result<DefaultJobReporter, Error> {
39 match conf {
40 None => {
41 return Err(Box::new(ConfLost));
42 }
43 Some(c) => {
44 if !c.is_object() {
45 return Err(Box::new(ConfInvalid("conf".into(), c.to_string())));
46 };
47 let kind = c["kind"]
48 .as_str()
49 .ok_or(ConfLostEntry("report.kind".into()))?;
50
51 match kind {
52 #[cfg(feature = "report_csv")]
53 "csv" => {
54 let v = c[kind].borrow();
55 let factory = csv::CsvJobReporter::new(
56 v["dir"]
57 .as_str()
58 .ok_or(ConfLostEntry("report.csv.dir".into()))?,
59 name.to_string(),
60 exec_id.to_string(),
61 v["with_bom"].as_bool().unwrap_or(true),
62 )
63 .await?;
64 return Ok(DefaultJobReporter {
65 delegate: Box::new(factory),
66 });
67 }
68 other => {
85 return Err(Box::new(ConfInvalid("kind".to_string(), other.to_string())))
86 }
87 }
88 }
89 }
90 }
91}
92
93#[async_trait]
94impl JobReporter for DefaultJobReporter {
95 async fn task(
96 &self,
97 task_id: Arc<dyn TaskId>,
98 flow: Arc<Flow>,
99 ) -> Result<Box<dyn TaskReporter>, Error> {
100 self.delegate.task(task_id, flow).await
101 }
102}