solution-forest/workflow-engine-core
Framework-agnostic workflow engine core for PHP 8.3+. Define and run workflows with type-safe steps, state tracking/persistence, plugins for actions/storage, retries, timeouts, and rich error handling. Actively developed; not production-ready.
Strengths:
WorkflowState transitions (e.g., PENDING → RUNNING → COMPLETED) map cleanly to Laravel’s event-driven architecture (e.g., ModelObserver lifecycle hooks).Queue system or Cache for persistence).Strict mode.WorkflowStartedEvent, StepFailedEvent) integrates naturally with Laravel’s Event facade or Broadcasting.Challenges:
data_get()/data_set() (Laravel helpers) violates framework-agnostic claims. Must replace with Arr::get() or similar.Queue, Cache, or Database systems (e.g., DatabaseStorageAdapter would require custom implementation).WorkflowEngine, WorkflowBuilder) are framework-agnostic and can be wrapped in Laravel service providers.Queue (for async execution), Cache (for persistence), or Database (for scalable storage).SimpleWorkflow for synchronous, in-memory workflows (e.g., CLI commands, admin panels).DatabaseStorageAdapter and QueueExecutor to leverage Laravel’s infrastructure.data_get() with Arr::get() and remove PHPStan suppressions.Executor ignores timeout config).data_get() usage will break in non-Laravel environments (already suppressed in PHPStan).setState()) risks invalid transitions (e.g., RUNNING → PENDING).SimpleWorkflow for non-critical paths; wrap WorkflowEngine in a Laravel service with fallback logic.DatabaseStorageAdapter) or can they be ephemeral (e.g., InMemoryStorage)?QueueExecutor (not implemented); sync limits scalability.Queue, Cache, or Database?QueueStorageAdapter).Exception handler, Slack alerts)?WorkflowFailedEvent) can trigger Laravel listeners.DatabaseMigrations or the package’s InMemoryStorage?InMemoryStorage is faster but doesn’t test persistence.Laravel Integration Points:
| Component | Laravel Equivalent | Integration Strategy |
|---|---|---|
| Storage | Database, Cache, Redis |
Implement DatabaseStorageAdapter or CacheStorageAdapter. |
| Async Execution | Queue |
Wrap WorkflowEngine in a QueuedWorkflowExecutor. |
| Event Dispatching | Event facade |
Dispatch WorkflowStartedEvent → Laravel’s event() method. |
| Logging | Log facade |
Replace NullLogger with LaravelLoggerAdapter. |
| Configuration | .env |
Bind WorkflowEngine to Laravel’s config() via service provider. |
| Testing | DatabaseMigrations, Mockery |
Use InMemoryStorage for unit tests; DatabaseStorageAdapter for integration tests. |
Recommended Stack:
WorkflowEngine + DatabaseStorageAdapter (for durability).Queue + QueuedWorkflowExecutor (for scalability).Event facade (for notifications).InMemoryStorage (unit) + DatabaseStorageAdapter (integration).Pilot Phase (1–2 weeks):
data_get() with Arr::get() (or data_get() polyfill).DatabaseStorageAdapter for basic persistence.SimpleWorkflow for synchronous, non-critical workflows (e.g., admin panels).Production-Ready Phase (2–4 weeks):
QueuedWorkflowExecutor to offload workflows to Laravel’s Queue.RetryMiddleware and TimeoutMiddleware (or contribute fixes to upstream).Event system (e.g., WorkflowFailedEvent → Slack alert).Optimization Phase (Ongoing):
InMemoryStorage with CacheStorageAdapter for high-throughput workflows.NotifyAction using Notification facade).data_get()).Strict mode.Event facade.Queue, Cache).data_get() dependency breaks framework-agnostic claim.data_get() with Arr::get() (blocker for non-Laravel use).TimeoutMiddleware (blocker for production use).WorkflowEngine in a Laravel service provider.DatabaseStorageAdapter.QueuedWorkflowExecutor for Laravel’s Queue.InMemoryStorage (unit) and DatabaseStorageAdapter (integration).data_get() replacement and custom adapters add maintenance overhead.WorkflowFailedEvent can trigger Laravel notifications (e.g., Slack, email).WorkflowInstance::getStatusSummary() provides debug info.QueuedWorkflowExecutor + Laravel’s Queue monitoring.RUNNING → PENDING) may cause silent failures.Queue/Cache.InMemoryStorage is fast but not durable.QueuedWorkflowExecutor + DatabaseStorageAdapterHow can I help you explore Laravel packages today?