Skip to content

Conversation

@kasvith
Copy link
Contributor

@kasvith kasvith commented Jan 22, 2026

Summary

  • Improve parallel execution with a new results-based model using tagged tuples
  • Remove the foreach primitive (users should use Enum.map/Task.async_stream instead)

Parallel Execution Changes

New Results Model

Parallel steps now produce results stored in __results__ as tagged tuples:

parallel do
  step :payment, fn ctx -> {:ok, %{id: 123}} end
  step :delivery, fn ctx -> {:error, :not_found} end
end

step :handle, fn ctx ->
  # Results are tagged tuples
  results = ctx[:__results__]
  # => %{payment: {:ok, %{id: 123}}, delivery: {:error, :not_found}}
end

New Helper Functions

  • parallel_results/0 - Get all results map
  • parallel_result/1 - Get specific step result
  • parallel_ok?/1 - Check if step succeeded

Custom Result Transformation with into:

parallel into: fn ctx, results ->
  case {results[:a], results[:b]} do
    {{:ok, a}, {:ok, b}} -> {:ok, Map.merge(ctx, %{a: a, b: b})}
    _ -> {:error, "failed"}
  end
end do
  step :a, fn ctx -> {:ok, %{value: 1}} end
  step :b, fn ctx -> {:ok, %{value: 2}} end
end

ForEach Removal (Breaking Change)

The foreach primitive is removed. Replace with:

# Sequential
step :process, fn ctx ->
  results = Enum.map(ctx.items, &process/1)
  {:ok, assign(ctx, :processed, results)}
end

# Concurrent
step :process, fn ctx ->
  results = Task.async_stream(ctx.items, &process/1, max_concurrency: 5)
  |> Enum.map(fn {:ok, r} -> r end)
  {:ok, assign(ctx, :processed, results)}
end

Files Changed

  • lib/durable/dsl/step.ex - Remove foreach macro
  • lib/durable/executor.ex - Remove foreach execution, update parallel
  • lib/durable/executor/step_runner.ex - Remove foreach handling
  • lib/durable/context.ex - Add parallel helpers, remove foreach helpers
  • guides/parallel.md - Document new results model
  • All guides updated with consistent examples

Test plan

  • All 256 tests pass
  • mix precommit passes

Users should use regular steps with Elixir's built-in enumeration tools
(Enum.map, Task.async_stream) for batch processing instead.

- Remove foreach macro from DSL
- Remove foreach execution from executor and step runner
- Remove foreach-related context functions (current_item, current_index)
- Delete foreach test file and guide
- Update integration tests to use Enum.map instead of foreach
- Update README batch processing example
- Update parallel guide with tagged tuple results model
- Add parallel_results/0, parallel_result/1, parallel_ok?/1 helpers docs
- Document into: option for custom result transformation
- Update all guides with consistent examples
- Update parallel tests for results-based model
@kasvith kasvith changed the title feat!: remove foreach primitive feat!: parallel execution improvements and foreach removal Jan 22, 2026
@kasvith kasvith merged commit 2eb8a5d into main Jan 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants