elf_rust/
wrap.rs

1use std::collections::HashMap;
2use crate::script::{BoxedScript, IntoScriptConfigs};
3use cloud_task_executor::*;
4use log::{debug, error, info};
5use serde_json::{json, Value};
6
7#[derive(Clone)]
8pub struct App {
9    scripts: Vec<BoxedScript>,
10}
11
12impl Default for App {
13    fn default() -> Self {
14        Self::new()
15    }
16}
17
18impl App {
19    pub fn new() -> Self {
20        Self {
21            scripts: Vec::new(),
22        }
23    }
24    pub fn add_script(&mut self, script: impl IntoScriptConfigs + 'static) -> &mut Self {
25        let script = script.into_script();
26        info!("adding script: {}, shortname: {}", script.name(),script.short_name());
27        self.scripts.push(script);
28        self
29    }
30    pub fn add_scripts(&mut self, scripts: Vec<impl IntoScriptConfigs + 'static>) -> &mut Self {
31        for script in scripts {
32            self.add_script(script);
33        }
34        self
35    }
36    pub fn scripts(&self) -> &Vec<BoxedScript> {
37        &self.scripts
38    }
39    async fn execute_task(&self, ctx: Context, payload: Value) -> Result<String, String> {
40        let task_names: Vec<String> = if let Some(tasks) = payload.get("tasks").and_then(|v| v.as_array()) {
41            tasks.iter().filter_map(|v| v.as_str().map(|s| s.to_string())).collect()
42        } else {
43            return Err("no tasks found in payload".to_string());
44        };
45        let mut result = HashMap::new();
46        let mut failed_result = HashMap::new();
47        let mut cost_time = HashMap::new();
48        let mut task_done = Vec::new();
49        for task_name in task_names {
50            for script in &self.scripts {
51                let short_name = script.short_name();
52                if script.name() == task_name || short_name == task_name {
53                    let script_name = script.name();
54                    debug!("executing script: {} start", script_name);
55                    let start = std::time::Instant::now();
56                    let script_result = script.run(ctx.clone(), payload.clone()).await;
57                    debug!("executing script: {} end, elapsed: {:?}", script_name, start.elapsed());
58                    cost_time.insert(script_name, start.elapsed().as_millis());
59                    match script_result {
60                        Ok(script_result) => {
61                            info!("script {} executed successfully, result: {}", script_name, script_result);
62                            result.insert(script_name, script_result);
63                        }
64                        Err(err) => {
65                            error!("script {} executed failed, error: {}", script_name, err);
66                            failed_result.insert(script_name, err);
67                        }
68                    }
69                    task_done.push(script_name);
70                }
71            }
72        }
73        Ok(json!({
74            "executed": task_done,
75            "success": result,
76            "failed": failed_result,
77            "cost_time": cost_time
78        }).to_string())
79    }
80}
81
82impl From<App> for Task {
83    fn from(val: App) -> Self {
84        Task::new("elf_script", move |ctx, payload| {
85            let app = val.clone();
86            Box::pin(async move {
87                app.execute_task(ctx, payload).await
88            })
89        })
90    }
91}