rust-viewflow 0.1.0

Rust workflow library inspired by Viewflow, compatible with Axum and Actix-web
Documentation
use std::collections::HashMap;
use std::sync::RwLock;

use crate::core::{TaskState, WorkflowResult, WorkflowState};
use crate::db::WorkflowDatabase;

pub struct MemoryDatabase {
    workflows: RwLock<HashMap<String, WorkflowState>>,
    tasks: RwLock<HashMap<String, TaskState>>,
}

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

impl MemoryDatabase {
    pub fn new() -> Self {
        Self {
            workflows: RwLock::new(HashMap::new()),
            tasks: RwLock::new(HashMap::new()),
        }
    }
}

#[async_trait::async_trait]
impl WorkflowDatabase for MemoryDatabase {
    async fn create_workflow(&self, workflow: &WorkflowState) -> WorkflowResult<()> {
        self.workflows
            .write()
            .expect("memory workflow lock poisoned")
            .insert(workflow.id.clone(), workflow.clone());
        Ok(())
    }

    async fn get_workflow(&self, workflow_id: &str) -> WorkflowResult<WorkflowState> {
        self.workflows
            .read()
            .expect("memory workflow lock poisoned")
            .get(workflow_id)
            .cloned()
            .ok_or_else(|| format!("Workflow '{}' not found", workflow_id).into())
    }

    async fn update_workflow(&self, workflow: &WorkflowState) -> WorkflowResult<()> {
        self.workflows
            .write()
            .expect("memory workflow lock poisoned")
            .insert(workflow.id.clone(), workflow.clone());
        Ok(())
    }

    async fn create_task(&self, task: &TaskState) -> WorkflowResult<()> {
        self.tasks
            .write()
            .expect("memory task lock poisoned")
            .insert(task.id.clone(), task.clone());
        Ok(())
    }

    async fn get_task(&self, task_id: &str) -> WorkflowResult<TaskState> {
        self.tasks
            .read()
            .expect("memory task lock poisoned")
            .get(task_id)
            .cloned()
            .ok_or_else(|| format!("Task '{}' not found", task_id).into())
    }

    async fn update_task(&self, task: &TaskState) -> WorkflowResult<()> {
        self.tasks
            .write()
            .expect("memory task lock poisoned")
            .insert(task.id.clone(), task.clone());
        Ok(())
    }

    async fn get_tasks_by_workflow(&self, workflow_id: &str) -> WorkflowResult<Vec<TaskState>> {
        let tasks = self
            .tasks
            .read()
            .expect("memory task lock poisoned")
            .values()
            .filter(|task| task.workflow_id == workflow_id)
            .cloned()
            .collect();
        Ok(tasks)
    }
}