A lightweight, in-memory workflow engine built with NestJS that executes tasks with dependencies, retries, timeouts, and parallel execution.
- โ Task dependencies and parallel execution
- โ Configurable retries with exponential backoff
- โ Task timeouts and error handling
- โ Lifecycle events and logging
- โ REST API with Swagger documentation
- โ
Decorator-based task definition (
@TaskStep) - โ Comprehensive test coverage
# Install dependencies
npm install
# Start development server
npm run start:dev
# Run tests
npm test| Method | Endpoint | Description |
|---|---|---|
POST |
/workflow/run-simple |
Execute simple workflow |
POST |
/workflow/run-dependencies |
Execute workflow with dependencies |
POST |
/workflow/run-parallel |
Execute parallel workflow |
POST |
/workflow/run-retry |
Execute workflow with retries |
POST |
/workflow/run-decorated |
Execute decorated workflow |
API Documentation: http://localhost:3000/api
import { WorkflowEngineService } from './workflow/workflow-engine.service';
const workflow = [
{
id: 'fetchData',
handler: async () => ({ users: [{ id: 1, name: 'John' }] }),
retries: 2,
timeoutMs: 1000,
},
{
id: 'processData',
dependencies: ['fetchData'],
handler: async () => ({ processed: true }),
},
];
const result = await workflowEngine.run(workflow);import { Injectable } from '@nestjs/common';
import { TaskStep } from './workflow/task.decorator';
@Injectable()
export class DataTasksService {
@TaskStep({ id: 'fetchData', retries: 2 })
async fetchData() {
return { users: [{ id: 1, name: 'John' }] };
}
@TaskStep({ id: 'processData', dependencies: ['fetchData'] })
async processData() {
return { processed: true };
}
}src/workflow/
โโโ workflow-engine.service.ts # Core execution engine
โโโ workflow-validator.service.ts # Task validation
โโโ retry-handler.service.ts # Retry logic
โโโ task-extractor.service.ts # Decorator extraction
โโโ workflow.controller.ts # REST API
โโโ interceptors/ # Response formatting
โโโ utils/ # Utility functions
โโโ *.spec.ts # Tests
MIT