// 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::task::Poll; use tokio::process::Command; use futures::{lock::Mutex, prelude::*, poll}; use lazy_static::lazy_static; use tokio::{prelude::*, spawn, task::JoinHandle}; use uuid::Uuid; pub type FutRes = UResult; lazy_static! { static ref FUT_RESULTS: Mutex>> = Mutex::new(HashMap::new()); } //TODO: waiter struct pub async fn append_task(task: impl Future + Send + 'static) -> Uuid { let fid = Uuid::new_v4(); let result = spawn(Box::pin(task)); FUT_RESULTS.lock().await.insert(fid, result); fid } pub async fn append_tasks(tasks: Vec + Send + 'static>) -> Vec { let mut fids = Vec::::new(); for f in tasks.into_iter() { let fid = append_task(f).await; fids.push(fid); } fids } pub async fn pop_task(fid: Uuid) -> JoinHandle { FUT_RESULTS.lock().await.remove(&fid).expect(&UError::NoTask(fid).to_string()) } pub 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 mut tasks = FUT_RESULTS .lock() .await; let task = tasks .get_mut(&fid) .expect(&UError::NoTask(fid).to_string()); let status = match poll!(task) { Poll::Pending => None, Poll::Ready(r) => Some(r.unwrap()) }; if status.is_some() { pop_task(fid).await; } status } pub async fn pop_completed(fids: Option>) -> Vec> { let fids = match fids { Some(v) => v, None => FUT_RESULTS.lock() .await .keys() .map(|k| *k) .collect::>() }; let mut completed: Vec> = vec![]; for fid in fids { completed.push(pop_task_if_completed(fid).await) } completed } pub async fn wait_for_task(fid: Uuid) -> FutRes { pop_task(fid).await.await.unwrap() } pub async fn wait_for_tasks(fids: Vec) -> Vec { let mut results = vec![]; for fid in fids { results.push(wait_for_task(fid).await); } results } pub async fn run_until_complete(task: impl Future + Send + 'static) -> FutRes { let fid = append_task(task).await; wait_for_task(fid).await }