Multi-Step Process

Jorge reviewing a control panel to see which stages have been resolved.

Table of contents


Problem

In distributed systems and backend processes, it’s common for a complex operation to require executing multiple sequential steps with dependencies between them: file creation, upload, response generation, validation, cleanup, etc.
Controlling this state flow is critical to:

  • Ensure each step executes in the correct order.
  • Allow for recovery in case of error or system restart.
  • Maintain data consistency even if the process is interrupted.

Without a clear strategy, the code can become fragile, difficult to scale, and prone to errors.


Solution

A stage-based state management function is implemented to control the advancement of a ProcessModel through its lifecycle.
The idea is to encapsulate the state transition logic in a single function that evaluates the current state and executes the corresponding action, until the process reaches its final state.

The pattern relies on a repeat-while loop that re-evaluates the state after each operation, ensuring transitions occur in a deterministic and resilient manner.

func checkProcess(
    _ process: ProcessModel
) async throws {
    var process = process
    var status = process.status

    repeat {
        status = process.status
        process = try await checkStatus(process)
    } while status != process.status
}

func checkStatus(
    _ process: ProcessModel
) async throws -> ProcessModel {
    switch process.status {
        case .filesCreated:
            try await _uploadFiles(process)
        case .filesUploaded:
            try await _createResponses(process)
        case .responsesCreated, .responsesReasoning:
            try await _checkResponses(process)
        case .responsesCompleted:
            try await _deleteFiles(process)
        case .filesDeleted:
            try await _deleteResponses(process)
        case .responsesDeleted:
            try await _finishResponses(process)
        case .responsesFinished:
            try await _deleteProcess(process)
        default: process
    }
}

Implementation key points:

  • State centralization: a single control point defines all transitions.
  • Continuous re-evaluation: the repeat-while loop allows automatic advancement as long as there are state changes.
  • Operation isolation: each switch case delegates to specialized functions (_uploadFiles, _createResponses, etc.), keeping the code clean and testable.

Result

This multi-stage process management pattern provides:

  • Resilience: each transition is atomic and can be retried if a failure occurs.
  • Scalability: adding new steps only requires adding a new case to the switch.
  • Clarity: the complete process flow is understood with a single read.

Application example: data processing pipelines, content publishing workflows, or any long-running process that requires precise control of each stage without compromising data integrity.

Keep coding, keep running πŸƒβ€β™‚οΈ