elf_rust 0.1.3

A simple task executor for cloud platform
Documentation
use std::collections::HashMap;
use crate::script::{BoxedScript, IntoScriptConfigs};
use cloud_task_executor::*;
use log::{debug, error, info};
use serde_json::{json, Value};

#[derive(Clone)]
pub struct App {
    scripts: Vec<BoxedScript>,
}

impl Default for App {
    fn default() -> Self {
        Self::new()
    }
}

impl App {
    pub fn new() -> Self {
        Self {
            scripts: Vec::new(),
        }
    }
    pub fn add_script(&mut self, script: impl IntoScriptConfigs + 'static) -> &mut Self {
        let script = script.into_script();
        info!("adding script: {}, shortname: {}", script.name(),script.short_name());
        self.scripts.push(script);
        self
    }
    pub fn add_scripts(&mut self, scripts: Vec<impl IntoScriptConfigs + 'static>) -> &mut Self {
        for script in scripts {
            self.add_script(script);
        }
        self
    }
    pub fn scripts(&self) -> &Vec<BoxedScript> {
        &self.scripts
    }
    async fn execute_task(&self, ctx: Context, payload: Value) -> Result<String, String> {
        let task_names: Vec<String> = if let Some(tasks) = payload.get("tasks").and_then(|v| v.as_array()) {
            tasks.iter().filter_map(|v| v.as_str().map(|s| s.to_string())).collect()
        } else {
            return Err("no tasks found in payload".to_string());
        };
        let mut result = HashMap::new();
        let mut failed_result = HashMap::new();
        let mut cost_time = HashMap::new();
        let mut task_done = Vec::new();
        for task_name in task_names {
            for script in &self.scripts {
                let short_name = script.short_name();
                if script.name() == task_name || short_name == task_name {
                    let script_name = script.name();
                    debug!("executing script: {} start", script_name);
                    let start = std::time::Instant::now();
                    let script_result = script.run(ctx.clone(), payload.clone()).await;
                    debug!("executing script: {} end, elapsed: {:?}", script_name, start.elapsed());
                    cost_time.insert(script_name, start.elapsed().as_millis());
                    match script_result {
                        Ok(script_result) => {
                            info!("script {} executed successfully, result: {}", script_name, script_result);
                            result.insert(script_name, script_result);
                        }
                        Err(err) => {
                            error!("script {} executed failed, error: {}", script_name, err);
                            failed_result.insert(script_name, err);
                        }
                    }
                    task_done.push(script_name);
                }
            }
        }
        Ok(json!({
            "executed": task_done,
            "success": result,
            "failed": failed_result,
            "cost_time": cost_time
        }).to_string())
    }
}

impl From<App> for Task {
    fn from(val: App) -> Self {
        Task::new("elf_script", move |ctx, payload| {
            let app = val.clone();
            Box::pin(async move {
                app.execute_task(ctx, payload).await
            })
        })
    }
}