chord_output/report/
mod.rs

1use 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// #[cfg(feature = "report_webhook")]
15// mod webhook;
16
17#[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                    // #[cfg(feature = "report_webhook")]
69                    // "webhook" => {
70                    //     let v = c[kind].borrow();
71                    //     let factory = webhook::WebhookJobReporter::new(
72                    //         v["url"]
73                    //             .as_str()
74                    //             .ok_or(ConfLostEntry("report.webhook.url".into()))?
75                    //             .to_string(),
76                    //         name.to_string(),
77                    //         exec_id.to_string(),
78                    //     )
79                    //     .await?;
80                    //     return Ok(DefaultJobReporter {
81                    //         delegate: Box::new(factory),
82                    //     });
83                    // }
84                    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}