solution-forest/workflow-engine-core

Framework-agnostic workflow engine for PHP applications

v0.0.2-alpha 2025-05-29 14:01 UTC

This package is not auto-updated.

Last update: 2025-05-30 09:06:33 UTC


README

PHPStan GitHub Tests Action Status GitHub Code Style Action Status Latest Version on Packagist

A powerful, framework-agnostic workflow engine for PHP applications. This core library provides comprehensive workflow definition, execution, and state management capabilities without any framework dependencies.

โš ๏ธ WARNING: DEVELOPMENT STATUSโš ๏ธ

This package is currently under active development and is NOT READY FOR PRODUCTION USE.

Features may be incomplete, APIs might change, and there could be breaking changes. Use at your own risk in development environments only.

๐Ÿ“‹ Requirements

  • PHP 8.3+ - Leverages modern PHP features for type safety and performance
  • Composer - For dependency management
  • No framework dependencies - Works with any PHP project

โœจ Features

  • ๐Ÿš€ Framework Agnostic: Works with any PHP framework or standalone applications
  • ๐Ÿ”’ Type Safe: Full PHP 8.3+ type safety with strict typing and generics
  • ๐Ÿ”ง Extensible: Plugin architecture for custom actions and storage adapters
  • ๐Ÿ“Š State Management: Robust workflow instance state tracking and persistence
  • โšก Performance: Optimized for high-throughput workflow execution
  • ๐Ÿ›ก๏ธ Error Handling: Comprehensive exception handling with detailed context
  • ๐Ÿ”„ Retry Logic: Built-in retry mechanisms with configurable strategies
  • โฑ๏ธ Timeouts: Step-level timeout controls for reliable execution
  • ๐Ÿ“‹ Conditions: Conditional workflow execution based on runtime data
  • ๐ŸŽฏ Events: Rich event system for monitoring and integration
  • ๐Ÿงช Well Tested: Comprehensive test suite with 160+ assertions

๐Ÿ“ฆ Installation

For Production Use

composer require solution-forest/workflow-engine-core

For Development

# Clone the repository
git clone https://github.com/solution-forest/workflow-engine-core.git
cd workflow-engine-core

# Install dependencies
composer install

# Run quality checks
composer ci

๐Ÿš€ Quick Start

Basic Workflow Definition

use SolutionForest\WorkflowEngine\Core\WorkflowBuilder;
use SolutionForest\WorkflowEngine\Core\WorkflowEngine;
use SolutionForest\WorkflowEngine\Core\WorkflowContext;
use SolutionForest\WorkflowEngine\Actions\BaseAction;

// Define custom actions
class ValidateOrderAction extends BaseAction
{
    public function execute(WorkflowContext $context): ActionResult
    {
        $orderId = $context->getData('order_id');
        
        // Your validation logic here
        if ($this->isValidOrder($orderId)) {
            return ActionResult::success(['validated' => true]);
        }
        
        return ActionResult::failure('Invalid order');
    }
}

// Create a workflow
$workflow = WorkflowBuilder::create('order-processing')
    ->addStep('validate', ValidateOrderAction::class)
    ->addStep('payment', ProcessPaymentAction::class)
    ->addStep('fulfillment', FulfillOrderAction::class)
    ->addTransition('validate', 'payment')
    ->addTransition('payment', 'fulfillment')
    ->build();

// Execute the workflow
$engine = new WorkflowEngine();
$context = new WorkflowContext(
    workflowId: 'order-processing',
    stepId: 'validate',
    data: ['order_id' => 123, 'customer_id' => 456]
);

$instance = $engine->start($workflow, $context);
$result = $engine->executeStep($instance, $context);

Advanced Features

Conditional Steps

use SolutionForest\WorkflowEngine\Attributes\Condition;

class ConditionalAction extends BaseAction
{
    #[Condition("data.amount > 1000")]
    public function execute(WorkflowContext $context): ActionResult
    {
        // This action only executes if amount > 1000
        return ActionResult::success();
    }
}

Retry Logic

use SolutionForest\WorkflowEngine\Attributes\Retry;

class ReliableAction extends BaseAction
{
    #[Retry(maxAttempts: 3, delay: 1000)]
    public function execute(WorkflowContext $context): ActionResult
    {
        // This action will retry up to 3 times with 1 second delay
        return ActionResult::success();
    }
}

Timeouts

use SolutionForest\WorkflowEngine\Attributes\Timeout;

class TimedAction extends BaseAction
{
    #[Timeout(seconds: 30)]
    public function execute(WorkflowContext $context): ActionResult
    {
        // This action will timeout after 30 seconds
        return ActionResult::success();
    }
}

๐Ÿ—๏ธ Architecture

The workflow engine follows a clean architecture pattern with clear separation of concerns:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Workflow      โ”‚
โ”‚   Builder       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
         โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Workflow      โ”‚โ—„โ”€โ”€โ”€โ”‚   Workflow      โ”‚
โ”‚   Definition    โ”‚    โ”‚   Engine        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚                       โ”‚
         โ–ผ                       โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚     Steps       โ”‚    โ”‚    Executor     โ”‚
โ”‚   & Actions     โ”‚    โ”‚                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚                       โ”‚
         โ–ผ                       โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚     State       โ”‚    โ”‚     Events      โ”‚
โ”‚   Manager       โ”‚    โ”‚   Dispatcher    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“ Workflow Builder

  • Purpose: Fluent interface for creating workflow definitions
  • Responsibilities:
    • Provides method chaining (.addStep(), .when(), .email(), etc.)
    • Validates workflow structure during construction
    • Creates immutable workflow definitions
    • Supports conditional steps and common patterns
  • Example: WorkflowBuilder::create('user-onboarding')->addStep(...)->build()

๐Ÿ“‹ Workflow Definition

  • Purpose: Immutable data structure representing a complete workflow
  • Responsibilities:
    • Contains workflow metadata (name, description, version)
    • Stores all steps and their relationships
    • Defines step execution order and conditions
    • Serves as a blueprint for workflow execution
  • Key data: Steps, transitions, conditions, metadata

โšก Workflow Engine

  • Purpose: Central orchestrator that manages workflow execution
  • Responsibilities:
    • Starts new workflow instances from definitions
    • Manages workflow lifecycle (start, pause, resume, cancel)
    • Coordinates between different components
    • Provides API for workflow operations
  • Main methods: start(), pause(), resume(), cancel(), getInstance()

๐ŸŽฏ Steps & Actions

  • Purpose: Individual workflow tasks and their implementations
  • Responsibilities:
    • Steps: Define what should happen (metadata, config, conditions)
    • Actions: Implement the actual business logic (execute() method)
    • Handle step-specific configuration (timeout, retry, conditions)
    • Support compensation actions for rollback scenarios
  • Examples: SendEmailAction, CreateUserAction, ValidateOrderAction

๐ŸŽฌ Executor

  • Purpose: Runtime engine that executes individual workflow steps
  • Responsibilities:
    • Executes actions in the correct sequence
    • Handles conditional execution based on workflow context
    • Manages timeouts and retry logic
    • Processes step transitions and flow control
    • Handles errors and compensation

๐Ÿ—„๏ธ State Manager

  • Purpose: Component responsible for workflow instance state persistence
  • Responsibilities:
    • Saves/loads workflow instances to/from storage
    • Tracks workflow execution state (running, paused, completed, failed)
    • Manages workflow context data
    • Handles state transitions and validation
    • Supports different storage adapters (database, file, memory)

๐Ÿ“ก Events Dispatcher

  • Purpose: Event system for monitoring and integration
  • Responsibilities:
    • Fires events during workflow execution
    • Enables workflow monitoring and logging
    • Supports custom event listeners
    • Provides hooks for external system integration
    • Events: WorkflowStarted, StepCompleted, WorkflowFailed, etc.

๐Ÿ”„ Data Flow

  1. Builder โ†’ creates โ†’ Definition
  2. Engine โ†’ uses Definition to create instances
  3. Engine โ†’ delegates to Executor for step execution
  4. Executor โ†’ runs โ†’ Steps & Actions
  5. State Manager โ†’ persists โ†’ workflow state
  6. Events Dispatcher โ†’ broadcasts โ†’ execution events

โœ… Architecture Benefits

  • Separation of concerns - each component has a single responsibility
  • Extensibility - you can swap out storage adapters, add custom actions
  • Testability - each component can be tested independently
  • Framework agnostic - no dependencies on specific frameworks
  • Type safety - full PHP 8.3+ type hints throughout

๐Ÿ”ง Configuration

Storage Adapters

Implement the StorageAdapter interface for custom storage:

use SolutionForest\WorkflowEngine\Contracts\StorageAdapter;

class CustomStorageAdapter implements StorageAdapter
{
    public function save(WorkflowInstance $instance): void
    {
        // Save workflow instance to your storage
    }

    public function load(string $instanceId): ?WorkflowInstance
    {
        // Load workflow instance from your storage
    }

    public function delete(string $instanceId): void
    {
        // Delete workflow instance from your storage
    }
}

Event Handling

Listen to workflow events:

use SolutionForest\WorkflowEngine\Contracts\EventDispatcher;

class CustomEventDispatcher implements EventDispatcher
{
    public function dispatch(object $event): void
    {
        // Handle workflow events
        match (get_class($event)) {
            'SolutionForest\WorkflowEngine\Events\WorkflowStarted' => $this->onWorkflowStarted($event),
            'SolutionForest\WorkflowEngine\Events\StepCompletedEvent' => $this->onStepCompleted($event),
            'SolutionForest\WorkflowEngine\Events\WorkflowCompletedEvent' => $this->onWorkflowCompleted($event),
            default => null,
        };
    }
}

Logging

Provide custom logging implementation:

use SolutionForest\WorkflowEngine\Contracts\Logger;

class CustomLogger implements Logger
{
    public function info(string $message, array $context = []): void
    {
        // Log info messages
    }

    public function error(string $message, array $context = []): void
    {
        // Log error messages
    }

    public function warning(string $message, array $context = []): void
    {
        // Log warning messages
    }
}

๐Ÿงช Development

Testing

Run the test suite:

# Run all tests
composer test

# Run tests with coverage
composer test:coverage

# Run specific test file
vendor/bin/pest tests/Unit/WorkflowEngineTest.php

# Run tests with detailed output
vendor/bin/pest --verbose

Code Quality

We use several tools to maintain high code quality:

# Static analysis with PHPStan
composer analyze

# Code formatting with Laravel Pint
composer pint

# Check code formatting without making changes
composer pint --test

# Run all quality checks
composer pint && composer analyze && composer test

Development Tools

  • Pest - Testing framework with expressive syntax
  • Pest Architecture Testing - Architectural constraints and code quality rules
  • PHPStan - Static analysis tool for catching bugs
  • Laravel Pint - Code style fixer built on PHP-CS-Fixer
  • Framework-agnostic - No Laravel dependencies in the core library

Configuration Files

  • phpstan.neon.dist - PHPStan configuration for static analysis
  • pint.json - Laravel Pint configuration for code formatting
  • phpunit.xml.dist - PHPUnit configuration for testing
  • .github/workflows/run-tests.yml - CI/CD pipeline configuration

Quality Standards

We maintain high code quality through:

  • 100% PHPStan Level 6 - Static analysis with no errors
  • Laravel Pint - Consistent code formatting following Laravel standards
  • Comprehensive Testing - 40 tests with 160+ assertions covering all core functionality
  • Type Safety - Full PHP 8.3+ type declarations and documentation
  • Continuous Integration - Automated quality checks on every commit

๐Ÿ“š Framework Integrations

This core library is framework-agnostic. For specific framework integrations:

๐Ÿค Contributing

We welcome contributions! Please see CONTRIBUTING.md for details.

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Credits

  • Solution Forest Team - Initial development and maintenance
  • Contributors - Thank you to all contributors who have helped improve this project

๐Ÿ”— Links