goblin-engine 0.1.0

A high-performance async workflow engine for executing scripts in planned sequences with dependency resolution
Documentation
use std::time::Duration;
use thiserror::Error;

pub type Result<T> = std::result::Result<T, GoblinError>;

#[derive(Error, Debug)]
pub enum GoblinError {
    #[error("Script not found: {name}")]
    ScriptNotFound { name: String },

    #[error("Plan not found: {name}")]
    PlanNotFound { name: String },

    #[error("Script execution failed: {script} - {message}")]
    ScriptExecutionFailed { script: String, message: String },

    #[error("Script execution timed out: {script} after {timeout:?}")]
    ScriptTimeout { script: String, timeout: Duration },

    #[error("Test failed for script: {script}")]
    TestFailed { script: String },

    #[error("Configuration error: {message}")]
    ConfigError { message: String },

    #[error("IO error: {0}")]
    IoError(#[from] std::io::Error),

    #[error("TOML parsing error: {0}")]
    TomlError(#[from] toml::de::Error),

    #[error("Serialization error: {0}")]
    SerializationError(#[from] toml::ser::Error),

    #[error("Invalid step configuration: {message}")]
    InvalidStepConfig { message: String },

    #[error("Circular dependency detected in plan: {plan}")]
    CircularDependency { plan: String },

    #[error("Missing input dependency: {step} requires {dependency}")]
    MissingDependency { step: String, dependency: String },

    #[error("Engine error: {message}")]
    EngineError { message: String },
}

impl GoblinError {
    pub fn script_not_found(name: impl Into<String>) -> Self {
        Self::ScriptNotFound { name: name.into() }
    }

    pub fn plan_not_found(name: impl Into<String>) -> Self {
        Self::PlanNotFound { name: name.into() }
    }

    pub fn script_execution_failed(script: impl Into<String>, message: impl Into<String>) -> Self {
        Self::ScriptExecutionFailed {
            script: script.into(),
            message: message.into(),
        }
    }

    pub fn script_timeout(script: impl Into<String>, timeout: Duration) -> Self {
        Self::ScriptTimeout {
            script: script.into(),
            timeout,
        }
    }

    pub fn test_failed(script: impl Into<String>) -> Self {
        Self::TestFailed {
            script: script.into(),
        }
    }

    pub fn config_error(message: impl Into<String>) -> Self {
        Self::ConfigError {
            message: message.into(),
        }
    }

    pub fn invalid_step_config(message: impl Into<String>) -> Self {
        Self::InvalidStepConfig {
            message: message.into(),
        }
    }

    pub fn circular_dependency(plan: impl Into<String>) -> Self {
        Self::CircularDependency { plan: plan.into() }
    }

    pub fn missing_dependency(step: impl Into<String>, dependency: impl Into<String>) -> Self {
        Self::MissingDependency {
            step: step.into(),
            dependency: dependency.into(),
        }
    }

    pub fn engine_error(message: impl Into<String>) -> Self {
        Self::EngineError {
            message: message.into(),
        }
    }
}