|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to coding agents when working with code in this repository. |
| 4 | + |
| 5 | +## Build and Development Commands |
| 6 | + |
| 7 | +```bash |
| 8 | +# Run all quality checks (preferred - includes formatter, credo, dialyzer, tests, etc.) |
| 9 | +mix check --no-retry |
| 10 | + |
| 11 | +# Run tests |
| 12 | +mix test # All tests |
| 13 | +mix test test/reactor/step_test.exs # Single test file |
| 14 | +mix test test/reactor/step_test.exs:14 # Single test at line |
| 15 | + |
| 16 | +# Individual checks (use mix check instead when possible) |
| 17 | +mix format # Format code |
| 18 | +mix format --check-formatted # Verify formatting |
| 19 | +mix credo --strict # Linting |
| 20 | +mix dialyzer # Type checking |
| 21 | + |
| 22 | +# Generate documentation |
| 23 | +mix docs # Also runs spark.cheat_sheets and spark.replace_doc_links |
| 24 | + |
| 25 | +# Spark DSL formatting |
| 26 | +mix spark.formatter --extensions Reactor.Dsl |
| 27 | +``` |
| 28 | + |
| 29 | +## Architecture Overview |
| 30 | + |
| 31 | +Reactor is a dynamic, concurrent, dependency-resolving saga orchestrator. It executes workflows as directed acyclic graphs (DAGs) with automatic dependency resolution and concurrent step execution. |
| 32 | + |
| 33 | +### Core Execution Flow |
| 34 | + |
| 35 | +1. **Define** - Reactor defined via DSL (`use Reactor`) or programmatically (`Reactor.Builder`) |
| 36 | +2. **Plan** - `Reactor.Planner` converts steps into a `libgraph` DAG based on argument dependencies |
| 37 | +3. **Execute** - `Reactor.Executor` processes the DAG, running async-ready steps concurrently |
| 38 | +4. **Compensate/Undo** - On failure, steps are compensated then previously successful steps are undone |
| 39 | + |
| 40 | +### Key Modules |
| 41 | + |
| 42 | +- `Reactor` (`lib/reactor.ex`) - Main API: `run/4`, `undo/3` |
| 43 | +- `Reactor.Step` (`lib/reactor/step.ex`) - Step behaviour with callbacks: `run/3`, `compensate/4`, `undo/4`, `backoff/4` |
| 44 | +- `Reactor.Dsl` (`lib/reactor/dsl.ex`) - Spark DSL definition |
| 45 | +- `Reactor.Executor` (`lib/reactor/executor.ex`) - DAG execution engine |
| 46 | +- `Reactor.Planner` (`lib/reactor/planner.ex`) - Converts steps to execution graph |
| 47 | +- `Reactor.Builder` (`lib/reactor/builder/`) - Programmatic reactor construction |
| 48 | + |
| 49 | +### Step Types (lib/reactor/step/) |
| 50 | + |
| 51 | +Built-in steps for common patterns: |
| 52 | +- `AnonFn` - Anonymous function steps (used by DSL `run fn ... end`) |
| 53 | +- `Compose` - Embed sub-reactors |
| 54 | +- `Map` - Process collections with nested steps |
| 55 | +- `Switch` - Conditional branching |
| 56 | +- `Group` - Shared before_all/after_all hooks |
| 57 | +- `Around` - Wrap step execution (e.g., transactions) |
| 58 | +- `Recurse` - Iterative/recursive patterns |
| 59 | + |
| 60 | +### Argument System |
| 61 | + |
| 62 | +Arguments define step dependencies and data flow: |
| 63 | +- `input(:name)` - Reference reactor input |
| 64 | +- `result(:step_name)` - Reference another step's result |
| 65 | +- `value(static)` - Static value |
| 66 | +- `element(:map_step)` - Current element in Map context |
| 67 | + |
| 68 | +Dependencies are automatically resolved from argument sources to build the execution graph. |
| 69 | + |
| 70 | +### DSL Transformation Pipeline |
| 71 | + |
| 72 | +1. DSL entities defined in `lib/reactor/dsl/` sections |
| 73 | +2. `Reactor.Dsl.Transformer` converts DSL to `Reactor.Step` structs |
| 74 | +3. `Reactor.Dsl.Verifier` validates configuration (return exists, no cycles, etc.) |
| 75 | + |
| 76 | +## Testing Patterns |
| 77 | + |
| 78 | +Tests use `ExUnit` with `async: true` where possible. Test support modules are in `test/support/`: |
| 79 | +- `Example.Step.*` - Sample step implementations for testing |
| 80 | +- Step modules can be tested in isolation using `Builder.new_step!/4` |
| 81 | + |
| 82 | +For deterministic testing of concurrent workflows, use `async?: false` on steps. |
| 83 | + |
| 84 | +## Conventions |
| 85 | + |
| 86 | +- Uses [conventional commits](https://www.conventionalcommits.org/) for changelog generation |
| 87 | +- REUSE compliant licensing (SPDX headers in all files) |
| 88 | +- Spark DSL formatter configured in `.formatter.exs` |
| 89 | +- Documentation follows Diátaxis framework (tutorials, how-to, explanation, reference) |
0 commit comments