Skip to main content
Siglo provides high-performance, functional combinators for concurrent execution, competitive racing, conditional routing, and bounded batch mapping. Designed around cooperative cancellation, state isolation, and deterministic merging, Siglo enables complex asynchronous coordination while preventing race conditions, unhandled rejections, and resource exhaustion.

1. Parallel Execution (parallel, all, allSettled, race)

parallel(...branches, options?)

Executes multiple steps, flows, or async functions concurrently. Each branch receives an isolated clone of the context, guaranteeing that sibling branches cannot mutate shared state during execution. Siglo supports both spread and array argument overloads:

Execution Modes

Set the mode using ParallelOptions:
  1. fail-fast (default, alias all):
    • Executes all branches concurrently.
    • If any branch throws or rejects, an internal AbortController triggers immediate cancellation across all sibling in-flight branches.
    • The workflow rejects immediately with the error of the first failed branch.
    • On completion, attaches $branches: BranchExecutionSummary[] and $timing: { durationMs: number }.
  2. allSettled:
    • Executes all branches to completion regardless of individual failures.
    • Accumulates fulfilled values as well as rejection reasons.
    • Context output contains:
      • Each branch’s result keyed by its step/function name (or { error: Error } if rejected).
      • $branches: An array of BranchExecutionSummary records detailing name, index, status ('completed' | 'failed'), duration, output, and error.
      • $settled: The raw PromiseSettledResult<any>[] array.
  3. race:
    • Resolves or rejects as soon as the first branch settles.
    • Automatically aborts losing branches via AbortController to avoid orphaned background work and resource leaks.

Convenience Combinators: all, allSettled, and race

Instead of passing { mode: '...' }, Siglo exports dedicated helper functions:

Merge Strategies

When branches complete, their outputs are integrated into the workflow context according to mergeStrategy:

Example: Collision Detection with mergeStrategy: 'error'

Example: Namespaced Merging with mergeStrategy: 'namespace'


2. Conditions and Branching (when, branch)

when(predicate, thenStep, elseStep?)

Executes conditional logic based on a synchronous or asynchronous predicate function:

Key Characteristics

  • Predicate Metadata: Receives (ctx, meta) where meta includes { attempt, stackId, namespace }.
  • Async Support: Predicate can return boolean or Promise<boolean>.
  • Omitted elseStep: If the predicate evaluates to false and no elseStep is defined, the step returns $skipped: true, $skippedBranches: ['then'], leaving the rest of context unmodified.
  • Traceability: Context metadata tracks $branchSelected ('then' or 'else') and $skippedBranches.

branch(selectorOrBranches, branchesMap?, defaultBranch?)

Multi-way branching supporting both function-driven selection and dictionary-based routing:

1. Function Selector Routing

2. Shorthand Object-First Routing

When a selector function is omitted, branch inspects ctx.branch, ctx.status, ctx.choice, or defaults to 'default':

Unmatched Branches

If the selector returns a key that is not in branchesMap and no defaultBranch is provided, the step gracefully skips:

3. Mapping with Bounded Concurrency (map)

Unbounded concurrency across large collections can exhaust memory, crash external APIs, or saturate database connection pools. The map combinator processes collections with strict concurrency limits and built-in backpressure.

map(itemsOrAccessor, processItem, options?)

Options Specification (MapOptions)

Advanced Map Patterns

1. Resilient Processing with stopOnError: false

When processing non-critical batches (e.g. bulk notifications or ingest pipelines), collect errors without halting execution:

2. Memory-Bounded Async Generators

map natively consumes AsyncIterable generators. Items are pulled on demand by the worker pool, preventing unbounded memory growth when processing millions of rows:

4. Cancellation & Signal Propagation

All Siglo concurrency combinators are deeply integrated with the standard AbortController and AbortSignal architecture:
  1. Outer Cancellation: Passing a signal into the parent workflow (flow.run(input, { signal })) aborts all active combinator branches, queues, and child workers immediately.
  2. Inner Signal Combination: Combinators use combineAbortSignals to merge outer signals with internal fail-fast controllers. When one branch in fail-fast or race terminates, sibling operations receive an abort notification.
  3. Cooperative Cancellation: Long-running child steps should register abort listeners or pass meta.signal to downstream HTTP or database clients:

5. Combinator Selection Guide