apalis-workflow 1.0.0

A flexible and composable task workflow engine for rust
Documentation
use std::{
    sync::{Arc, atomic::AtomicU64},
    task::Waker,
};

use apalis_core::{backend::TaskResult, task::task_id::TaskId};
use dashmap::DashMap;

use crate::in_memory::stream::WaitId;

#[derive(Debug, Clone)]
pub struct ResultStore {
    pub(super) results: Arc<DashMap<TaskId, TaskResult<serde_json::Value>>>,
    pub(super) next_id: Arc<AtomicU64>,
    pub(super) wakers: Arc<DashMap<WaitId, Waker>>,
}

impl Default for ResultStore {
    fn default() -> Self {
        Self {
            results: Arc::new(DashMap::new()),
            wakers: Arc::new(DashMap::new()),
            next_id: Default::default(),
        }
    }
}

impl ResultStore {
    pub fn insert(&self, task_id: TaskId, result: TaskResult<serde_json::Value>) {
        self.results.insert(task_id, result);
        self.wake_all();
    }

    pub fn get(&self, task_id: &TaskId) -> Option<TaskResult<serde_json::Value>> {
        self.results.get(task_id).map(|a| a.clone())
    }

    pub fn register_waker(&self, id: WaitId, waker: &Waker) {
        self.wakers.insert(id, waker.clone());
    }

    fn wake_all(&self) {
        let ids: Vec<WaitId> = self.wakers.iter().map(|e| *e.key()).collect();

        for id in ids {
            if let Some((_, waker)) = self.wakers.remove(&id) {
                waker.wake_by_ref();
            }
        }
    }
}