// 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::task::Poll; use futures::{lock::Mutex, prelude::*, poll}; use lazy_static::lazy_static; use tokio::{prelude::*, spawn, task::JoinHandle}; use uuid::Uuid; use crate::OneOrMany; pub type FutRes = UResult; lazy_static! { static ref FUT_RESULTS: Mutex>> = Mutex::new(HashMap::new()); } pub struct Waiter where T: Future + Send + 'static { tasks: Vec, fids: Vec } impl Waiter where T: Future + Send + 'static { pub fn new>(tasks: S) -> Self { Self { tasks: tasks.into_vec(), fids: vec![] } } pub async fn spawn(mut self) -> Self { for f in self.tasks.drain(..) { let fid = Uuid::new_v4(); let result = spawn(Box::pin(f)); FUT_RESULTS.lock().await.insert(fid, result); self.fids.push(fid); } self } // wait until a bunch of tasks is finished // NOT GUARANTEED that all tasks will be returned due to // possibility to pop them in other places pub async fn wait(self) -> Vec { let mut result = vec![]; for fid in self.fids { if let Some(task) = pop_task(fid).await { result.push(task.await.unwrap()); } } result } pub async fn run_until_complete(self) -> Vec { self.spawn().await.wait().await } pub async fn run_one_until_complete(self) -> FutRes { self.run_until_complete().await.pop().unwrap() } } async fn pop_task(fid: Uuid) -> Option> { FUT_RESULTS.lock().await.remove(&fid) } 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() -> Vec { let fids = FUT_RESULTS.lock() .await .keys() .map(|k| *k) .collect::>(); let mut completed: Vec = vec![]; for fid in fids { if let Some(r) = pop_task_if_completed(fid).await { completed.push(r); } } 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 }*/