// list of jobs: job (cmd, args) OR rust fn OR python func + cron-like timing // job runner (thread) // every job runs in other thread/process use crate::{models::*, UResult, UError}; use std::collections::HashMap; use std::pin::Pin; use std::thread::sleep; use std::time::{Duration, Instant}; use std::slice::Iter; use std::task::Poll; use tokio::process::Command; use futures::{lock::Mutex, prelude::*}; use lazy_static::lazy_static; use tokio::{prelude::*, spawn, task::JoinHandle}; use uuid::Uuid; pub type FutRes = UResult; type BoxFut = Pin + Send + 'static>>; lazy_static! { static ref FUT_RESULTS: Mutex>> = Mutex::new(HashMap::new()); } pub async fn append_tasks(tasks: Vec + Send + 'static>) -> Vec { let mut fids = Vec::::new(); for f in tasks.into_iter() { let fid = Uuid::new_v4(); fids.push(fid); let result = spawn(Box::pin(f)); FUT_RESULTS.lock().await.insert(fid, result); } fids } pub async fn append_task(task: impl Future + Send + 'static) -> Uuid { append_tasks(vec![Box::pin(task)]).await[0] } pub async fn pop_task(fid: Uuid) -> JoinHandle { FUT_RESULTS.lock().await.remove(&fid).expect(&UError::NoTask(fid).to_string()) } async fn task_present(fid: Uuid) -> bool { FUT_RESULTS.lock().await.get(&fid).is_some() } pub async fn pop_task_if_completed(fid: Uuid) -> Option{ let task = FUT_RESULTS .lock() .await .get_mut(&fid) .expect(&UError::NoTask(fid).to_string()); let status = match task.poll() { Poll::Pending => None, Poll::Ready(r) => Some(r.unwrap()) }; if status.is_some() { pop_task(fid); } status } pub async fn pop_completed(fids: Option>) -> Vec> { match fids { Some(v) => v, None => FUT_RESULTS.lock() .await .keys() .map(|k| *k) .collect::>() }.into_iter().map(pop_task_if_completed).collect() } pub async fn run_until_complete(task: impl Future + Send + 'static) -> FutRes { let task_fid = append_task(task).await; pop_task(task_fid).await.await.unwrap() }