# `Runic.Runner.Executor.GenStage`
[🔗](https://github.com/zblanco/runic/blob/main/lib/runic/runner/executor/gen_stage.ex#L1)

GenStage-based executor providing demand-driven dispatch with back-pressure.

Uses a GenStage Producer + Consumer pool architecture. The Producer buffers
work items and Consumers pull them on demand, providing natural back-pressure
that prevents the Worker from overwhelming available compute.

Each consumer processes one work item at a time (`max_demand: 1`). The number
of consumers controls the concurrency level. Work items that arrive when all
consumers are busy are buffered in the Producer until demand is available.

## Options

  * `:max_demand` — number of concurrent consumers (default: `System.schedulers_online()`)
  * `:buffer_size` — producer event buffer size (default: `:infinity`)

## Architecture

```
Worker (caller)
    │ dispatch/3 → cast to Producer
    ▼
GenStage.Producer (buffers {handle, work_fn, caller} events)
    │
    ├──────────────────┤
    ▼                  ▼
Consumer 1         Consumer N
(execute work_fn)  (execute work_fn)
    │                  │
    └──── send {handle, result} / {:DOWN, handle, ...} to caller ────┘
```

## Message Contract

Preserves the standard Executor message contract:

  * `{handle, result}` — sent to caller on successful completion
  * `{:DOWN, handle, :process, pid, reason}` — sent to caller on failure

Failures are caught inside the consumer via `try/catch`, so individual work
item failures do not crash the consumer process.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
