Multicast and WireTap¶
pkg/processor/multicast.go defines the broadcast/fan-out primitives: Multicast EIP sends a copy of an exchange to N processors and optionally aggregates their responses; Wire Tap EIP forks an asynchronous side-channel copy while the original exchange continues unchanged.
Processors in this file¶
NewMulticast¶
Sends a copy of the exchange to every processor in the list. If Parallel is true the processors run concurrently; otherwise sequentially. Without an aggregation strategy, multicast is fire-and-forget (responses are dropped). With a strategy, the merged result replaces the original body.
YAML form:
steps:
- multicast:
uris:
- kafka://orders
- log://orders-audit
- http://localhost:8081/replica
parallel: true
strategy: list
| Field | Type | Default | Description |
|---|---|---|---|
uris |
list | required | Target URIs, resolved through the route's EndpointResolver. |
parallel |
bool | false |
Run targets concurrently. With false, targets run in declared order. |
strategy |
string | none | Built-in aggregation strategy. One of list, latest, first, useOriginal, map. If unset, responses are dropped. |
Constructor: NewMulticast(parallel bool, processors ...engine.Processor) *Multicast or NewMulticastWithStrategy(parallel bool, strategy, processors...).
How it works:
- Per processor: copy the exchange, set
HelixMulticastIndex, run the processor with the copy. - Sequential mode runs them in declared order; parallel mode spawns one goroutine per processor and waits with a
sync.WaitGroup. - If
Strategyis set, results are merged in deterministic index order (so output is reproducible even in parallel mode).useOriginalis a fast-path that skips aggregation entirely. - Any processor error becomes a
multicast[i] error: ...and the multicast returns that error after waiting for all parallel siblings. In sequential mode, errors fail-fast.
Notes and gotchas:
- Order: with
parallel: trueand an aggregation strategy, the aggregation is done in index order — not completion order — so the resulting list/map is stable. - A processor that does its own publishing (e.g.
target: kafka://x) typically returns no useful body; pair it withuseOriginalstrategy to keep the source body. - Multicast does not roll back successful siblings if a later sibling fails. Use
Sagafor compensation.
NewWireTap¶
Sends a copy of the exchange to a side processor in a goroutine and returns immediately. Errors and panics inside the tap are logged but never propagated.
| Field | Type | Default | Description |
|---|---|---|---|
wiretap |
string | required | Target URI (e.g. kafka://audit-log). The YAML form is a single string. |
Constructor: NewWireTap(processor engine.Processor) *WireTap.
How it works:
ex.Copy()— produces a shallow copy of the exchange.- Launches a goroutine that processes the copy. A
defer recover()wraps the call so a panic in the tap is logged but does not kill the parent. - Returns
nilimmediately — the original exchange continues in the parent pipeline.
Pitfalls:
ex.Copy()is shallow. If you mutate a shared body slice/map inside the tap, you risk a data race with the parent. UseWireTapEIPwithdeepCopyEnabled: truefor full isolation.- Tap errors are not observable in the parent route. If you need backpressure or error feedback, use
multicastwith a strategy instead.
Examples¶
Broadcast with response collection:
workflows:
- id: query-all-shards
trigger: { uri: http://localhost:8080/q }
steps:
- multicast:
parallel: true
strategy: list
uris:
- http://shard-1/q
- http://shard-2/q
- http://shard-3/q
- transform:
starlang: |
%sl 2.0
output application/json
input payload
---
{ "results": payload }
Async audit log:
workflows:
- id: audited-publish
trigger: { uri: direct://orders }
steps:
- wiretap: kafka://audit
- target: kafka://orders
Source¶
pkg/processor/multicast.go
See also¶
- aggregate — full list of built-in
AggregationStrategyimplementations. - routing —
RecipientList(dynamic URIs),RoutingSlip(sequential),DynamicRouter(iterative). - eip_advanced —
WireTapEIPwith deep-copy and main-pipeline integration. - eip_advanced —
ScatterGatherfor multicast + gather with a single timeout.