ORCHWF is a powerful Go package for orchestrating complex workflows with support for both synchronous and asynchronous execution patterns. It provides flexible state management options (in-memory or database) and uses Go routines for async execution instead of external queue systems.
- Dual Execution Modes: Synchronous and asynchronous workflow execution
- Flexible State Management: In-memory or database persistence
- Dependency Management: Step dependencies with parallel execution support
- Retry Logic: Configurable retry policies with exponential backoff
- Event System: Comprehensive workflow and step event tracking
- Transaction Support: Database transaction support for consistency
- Builder Pattern: Fluent API for building workflows and steps
- Pure Go: Uses only Go standard library (no external dependencies except UUID)
go get github.com/refactorroom/orchwfpackage main
import (
"context"
"fmt"
"log"
"github.com/refactorroom/orchwf"
)
func main() {
// Create in-memory state manager
stateManager := orchwf.NewInMemoryStateManager()
// Create orchestrator
orchestrator := orchwf.NewOrchestrator(stateManager)
// Define a simple step
step1, _ := orchwf.NewStepBuilder("step1", "Process Data", func(ctx context.Context, input map[string]interface{}) (map[string]interface{}, error) {
fmt.Println("Processing data...")
return map[string]interface{}{
"result": "processed",
}, nil
}).Build()
// Build workflow
workflow, _ := orchwf.NewWorkflowBuilder("simple_workflow", "Simple Workflow").
AddStep(step1).
Build()
// Register workflow
orchestrator.RegisterWorkflow(workflow)
// Execute workflow
result, err := orchestrator.StartWorkflow(context.Background(), "simple_workflow",
map[string]interface{}{"data": "test"}, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Workflow completed: %+v\n", result)
}package main
import (
"database/sql"
"log"
_ "github.com/lib/pq" // PostgreSQL driver
"github.com/refactorroom/orchwf"
)
func main() {
// Connect to database
db, err := sql.Open("postgres", "postgres://user:password@localhost/dbname?sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// Create database state manager
stateManager := orchwf.NewDBStateManager(db)
// Create orchestrator
orchestrator := orchwf.NewOrchestrator(stateManager)
// Run migrations (you need to implement this)
// runMigrations(db)
// Use orchestrator...
}Perfect for development, testing, or simple workflows:
stateManager := orchwf.NewInMemoryStateManager()Pros:
- Fast execution
- No database setup required
- Perfect for testing
Cons:
- Data lost on restart
- Not suitable for production
Production-ready persistence using standard database/sql:
db, _ := sql.Open("postgres", connectionString)
stateManager := orchwf.NewDBStateManager(db)Pros:
- Persistent storage
- Transaction support
- Production ready
- Scalable
Cons:
- Requires database setup
- Slightly slower than in-memory
All steps run in sequence, waiting for each to complete:
result, err := orchestrator.StartWorkflow(ctx, "workflow_id", input, metadata)Workflow starts immediately and runs in background:
workflowID, err := orchestrator.StartWorkflowAsync(ctx, "workflow_id", input, metadata)Steps can be marked as async within a workflow:
step1, _ := orchwf.NewStepBuilder("step1", "Sync Step", syncExecutor).
WithAsync(false).
Build()
step2, _ := orchwf.NewStepBuilder("step2", "Async Step", asyncExecutor).
WithAsync(true).
WithDependencies("step1").
Build()retryPolicy := orchwf.NewRetryPolicyBuilder().
WithMaxAttempts(3).
WithInitialInterval(1 * time.Second).
WithMultiplier(2.0).
WithMaxInterval(30 * time.Second).
WithRetryableErrors("network_error", "timeout").
Build()
step, _ := orchwf.NewStepBuilder("step", "Name", executor).
WithRetryPolicy(retryPolicy).
Build()step1, _ := orchwf.NewStepBuilder("step1", "First Step", executor1).Build()
step2, _ := orchwf.NewStepBuilder("step2", "Second Step", executor2).
WithDependencies("step1").
Build()
step3, _ := orchwf.NewStepBuilder("step3", "Third Step", executor3).
WithDependencies("step1", "step2").
Build()step, _ := orchwf.NewStepBuilder("step", "Name", executor).
WithTimeout(30 * time.Second).
Build()Steps that don't stop the workflow on failure:
step, _ := orchwf.NewStepBuilder("step", "Optional Step", executor).
WithRequired(false).
Build()Run the migration script:
-- See migrations/001_create_orchwf_tables.sqlThe package uses standard SQL, so it should work with any database that supports:
- JSON/JSONB columns
- Standard SQL syntax
- Transactions
NewOrchestrator(stateManager)- Create new orchestratorNewOrchestratorWithAsyncWorkers(stateManager, workers)- Create with custom worker countRegisterWorkflow(workflow)- Register a workflow definitionStartWorkflow(ctx, id, input, metadata)- Start workflow synchronouslyStartWorkflowAsync(ctx, id, input, metadata)- Start workflow asynchronouslyResumeWorkflow(ctx, instanceID)- Resume a failed workflowGetWorkflowStatus(ctx, instanceID)- Get workflow statusListWorkflows(ctx, filters, limit, offset)- List workflows
NewInMemoryStateManager()- Create in-memory state managerNewDBStateManager(db)- Create database state manager
NewWorkflowBuilder(id, name)- Create workflow builderNewStepBuilder(id, name, executor)- Create step builderNewRetryPolicyBuilder()- Create retry policy builder
See the examples/ directory for complete working examples.
MIT License - see LICENSE file for details.