How mahabubulhasibshawon/task_saga_workflow_orchestrator works
1. Overall shape
- This repository is a Go-based Saga workflow orchestrator for order processing.
- It follows a clean architecture split: cmd entrypoints → internal/usecases business logic → internal/repositories persistence → internal/adapters integration concerns.
- The system coordinates long-running workflows with forward steps, compensation steps, and recovery.
2. Runtime entrypoints
- cmd/orchestrator is the main worker process: it starts the workflow execution runtime, queue consumers, metrics, and tracing.
- cmd/simulate generates synthetic orders to drive the workflow.
- cmd/recover scans for stalled workflows and resumes them.
- These are separate binaries rather than one monolith, which is important for the deployment diagram.
3. Workflow control plane
- internal/usecases/workflow.go and internal/usecases/compensation.go are the orchestration core.
- They decide the current step, advance the saga, and trigger rollback when a step fails.
- The workflow model is step-based, with forward steps like reserve_pickup_slot → assign_agent → notify_customer and compensation steps like unassign_agent → release_slot → cancel_notification.
4. Domain model boundaries
- internal/domain contains the core entities and interfaces:
- order.go
- workflow_state.go
- repository interfaces for orders, agents, workflow state, and step execution
- This layer defines the business concepts without depending on Postgres, Redis, or queue libraries.
- The domain interfaces are the boundary that the repositories implement.
5. Persistence layer
- internal/repositories contains concrete database access for orders, workflows, agents, and step executions.
- The schema is split across four tables:
- orders for order status
- workflows for current step and overall state
- step_executions for idempotency and deduplication
- agents for multiple agents assigned per order
- This persistence layer is the source of truth for workflow state and retry safety.
6. Queue and task execution
- internal/adapters/queue and internal/adapters/handlers connect the workflow logic to background task execution.
- The README indicates the queue runtime is based on Asynq, with Redis acting as the task broker.
- The queue boundary is where workflow steps are dispatched asynchronously and retried independently of the CLI that initiated them.
7. External infrastructure
- docker-compose.yml provisions the required infrastructure: Postgres and Redis.
- pkg/conn/postgress.go centralizes the Postgres connection setup.
- The architecture therefore depends on two backing services:
- Postgres for durable workflow state
- Redis for task queue transport
8. Observability
- internal/adapters/metrics exposes Prometheus metrics for step success, step failure, and compensation counts.
- internal/adapters/tracing wires in OpenTelemetry for distributed tracing across workflow steps.
- cmd/orchestrator is the process where these observability adapters matter most, because it is the active worker handling workflow transitions.
9. Failure handling and recovery
- The saga is designed to tolerate partial failure: if a forward step fails, compensation is executed for prior completed steps.
- Idempotency is handled through step_executions, so re-delivered tasks or retried steps do not duplicate side effects.
- cmd/recover provides an explicit recovery path for workflows left in an in-between state after crashes or outages.
10. Mockable service boundary
- pkg/mocks contains in-memory or DB-backed service stand-ins used by the workflow logic.
- This suggests the step execution side effects are abstracted so the orchestrator can be tested or simulated without real downstream microservices.
- For architecture diagrams, this is the “external business services” boundary even though the repo currently ships with mocks.
11. Schema evolution
- migrations/ contains versioned SQL migrations for all durable entities.
- This means the workflow state machine is strongly coupled to the relational schema, and deployment requires database migration before running the orchestrator.
- The DB schema is part of the system contract, not just an implementation detail.
12. End-to-end data flow
- simulate creates orders.
- Order state is persisted in Postgres.
- The orchestrator schedules and processes saga steps via the queue.
- Each step updates workflow state and step execution history.
- On success, the workflow advances; on failure, compensation is triggered.
- Metrics and traces are emitted throughout the process, and recover can resume incomplete workflows later.
13. Key architectural boundaries to draw
- Boundary 1: CLI entrypoints vs. long-running worker/runtime.
- Boundary 2: orchestration/use case layer vs. persistence implementation.
- Boundary 3: core workflow domain vs. queue/metrics/tracing adapters.
- Boundary 4: durable Postgres state vs. ephemeral Redis queue state.
- Boundary 5: orchestrator core vs. mocked downstream business services.
Main entry points: workflow.go Workflow usecase · main.go Orchestrator · docker-compose.yml Postgres · handlers.go Handlers
Components 24
Entry points
Separate binaries that start, drive, or recover workflow execution.
- Orchestrator · Main long-running process that executes saga steps and coordinates runtime concerns.
cmd/orchestrator/main.go - Simulate · Creates synthetic orders to drive the workflow end to end.
cmd/simulate/main.go - Recover · Scans for stalled workflows and resumes incomplete executions.
cmd/recover/main.go
Core workflow
Domain and use cases that implement saga orchestration logic.
- Workflow usecase · Advances saga steps, decides next actions, and coordinates forward execution.
internal/usecases/workflow.go - Compensation usecase · Triggers and sequences compensating actions when a forward step fails.
internal/usecases/compensation.go - Order model · Core order business object and state.
internal/domain/order.go - Workflow state · Saga state machine data and current step tracking.
internal/domain/workflow_state.go - Order repo iface · Persistence boundary for order data access.
internal/domain/order_repo_interface.go - Agent repo iface · Persistence boundary for agent assignment data.
internal/domain/agent_repo_interface.go - Workflow repo iface · Persistence boundary for workflow state and step progression.
internal/domain/workflow_state_repo_interface.go - Step exec iface · Boundary for idempotency and step execution history.
internal/domain/step_execution_repo_interface.go
Persistence
Postgres-backed repositories, schema migrations, and connection setup.
- Order repo · Concrete persistence for orders table.
internal/repositories/order_repo.go - Agent repo · Concrete persistence for agents table and assignment records.
internal/repositories/agent_repo.go - Workflow repo · Stores current workflow state and overall saga progress.
internal/repositories/workflow_repo.go - Step exec repo · Stores step execution history for retry safety and deduplication.
internal/repositories/step_execution_repo.go - Migrations · Versioned schema for orders, agents, workflows, and step executions.
migrations/003_create_workflows.up.sql - Postgres conn · Shared Postgres connection setup used by repositories and runtime.
pkg/conn/postgress.go
Adapters
Queue, handlers, observability, and external service boundaries.
- Queue adapter · Dispatches saga steps asynchronously through Redis-backed tasks.
internal/adapters/queue/queue.go - Handlers · Executes queued workflow step tasks and invokes use cases.
internal/adapters/handlers/handlers.go - Metrics · Emits step success, failure, and compensation counters.
internal/adapters/metrics/metrics.go - Tracing · Propagates distributed traces across workflow execution.
internal/adapters/tracing/tracing.go - Service mocks · Stand-ins for downstream business services used by workflow execution.
pkg/mocks/services.go
Connections 25
- Simulate → Workflow usecase: creates orders · Synthetic orders enter the orchestration flow through the business logic.
- Orchestrator → Queue adapter: runs tasks · Main worker consumes and dispatches saga work through the queue.
- Orchestrator → Handlers: executes steps · Worker runtime invokes task handlers for workflow step execution.
- Orchestrator → Metrics: emits · Worker process publishes execution metrics.
- Orchestrator → Tracing: traces · Worker process participates in distributed tracing.
- Recover → Workflow usecase: resumes · Recovery process re-enters stalled workflows through orchestration logic.
- Handlers → Workflow usecase: advances · Queue tasks delegate step progression to the workflow use case.
- Workflow usecase → Compensation usecase: on failure · Failed forward steps trigger compensation sequencing.
- Workflow usecase → Order model: uses · Workflow logic operates on order state.
- Workflow usecase → Workflow state: uses · Workflow logic reads and updates saga state.
- Workflow usecase → Order repo iface: depends on · Use case depends on the order persistence boundary.
- Workflow usecase → Agent repo iface: depends on · Use case depends on agent assignment boundary.
- Workflow usecase → Workflow repo iface: depends on · Use case depends on workflow state boundary.
- Workflow usecase → Step exec iface: depends on · Use case depends on step execution history boundary.
- Compensation usecase → Step exec iface: records · Compensation uses step execution history for safe retries.
- Order repo → Postgres: stores in · Order repository persists to Postgres.
- Agent repo → Postgres: stores in · Agent repository persists to Postgres.
- Workflow repo → Postgres: stores in · Workflow repository persists to Postgres.
- Step exec repo → Postgres: stores in · Step execution repository persists to Postgres.
- Migrations → Postgres: defines schema · SQL migrations create and evolve the durable schema.
- Postgres conn → Postgres: connects · Shared connection setup targets Postgres.
- Queue adapter → Redis: brokers on · Asynq queue adapter uses Redis as task transport.
- Handlers → Queue adapter: consumes from · Handlers process queued step jobs.
- Handlers → Service mocks: calls · Workflow steps interact with mocked downstream business services.
- Orchestrator → Postgres conn: initializes · Worker starts database connectivity during boot.