Structured Concurrency

Structured concurrency is a programming paradigm that Obelisk employs to manage child executions (child workflows and activities). It ensures that the lifetimes of concurrent tasks are contained within the scope of their parent execution, meaning that the parent workflow execution is blocked until its child executions finish or are cancelled.

This approach simplifies resource management, cleanup and error handling.

At its core, structured concurrency in Obelisk revolves around managing a tree structure of executions.

The Execution Tree

  1. Root Execution: It all starts with a single top-level execution, which is typically a workflow triggered by an external event or a webhook endpoint .
  2. Parent-Child Relationship: Workflows can spawn child executions. These children can be other workflows or activities . Only activities are permitted to perform side effects, such as making external HTTP calls. Workflows orchestrate these activities and other workflows in a deterministic and thus replayable fashion.
  3. Controlled Lifetimes: A fundamental guarantee of structured concurrency is that child executions cannot outlive their parent. When a parent workflow finishes (either successfully or due to an error), Obelisk ensures that all its direct children are also properly concluded before the grand-parent is notified.

Error Propagation

Structured concurrency provides clear rules for how errors are handled within the execution tree:

  1. Child to Parent: If a child execution fails – whether by returning an error, panicking (trapping within the WASM sandbox), or timing out – and the configured amount of retries is exhausted – the last execution error is propagated upwards to its immediate parent workflow.
  2. Bubbling Up Unhandled errors: If the parent workflow does not explicitly handle the error from its child, the error continues to bubble up the execution tree.
  3. Root Failure: An unhandled error that reaches the root execution will cause the entire top-level execution to be marked as failed.

This ensures that failures are not lost and that the system maintains a consistent state.

The Role of Join Sets

            [Join Sets](@/docs/v0.24.1/concepts/workflows/join-sets.md)

are the primary mechanism Obelisk uses to implement and enforce structured concurrency.

Contrast with Unstructured Concurrency (-schedule)

Obelisk also provides the -schedule extension function. It's important to understand that using -schedule opts out of the structured concurrency model for that specific execution:

Benefits of Structured Concurrency