Countdown loop
One message carries an array; you want one outbound call per element but you do not want to debatch it into N independent messages. A countdown loop keeps the batch whole and iterates it on the bus: a counter variable gates a send port that processes one element, decrements, and re-publishes itself until the counter reaches zero.
Most orchestration-replacement patterns wait on correlation, which is still on the roadmap. The countdown loop is the one you can build today, precisely because it never needs to hold or merge state across instances. It is a strictly linear construct: within a single loop one pass is in flight at a time, and it self-correlates through a counter that only ever counts down.
The receive port's inbound pipeline counts the repeating node on the way in with a one-line component, components are the write surface for variables, and the platform's JSONPath engine (Newtonsoft.Json) has no length function, so the count comes from code: A send port subscribes to the message type and the counter being above zero; on each pass it reads the element at the current index, makes its call, and decrements the counter. The republish is the two-way response, and a two-way port publishes back what the call returned, so the call must return the original message: the procedure takes the whole body as a parameter and echoes it, the response-side map unwraps the echo, and Publish Message Type Fallback stamps the same message type, so the message re-enters the bus and the same port matches again. Each pass the counter shrinks by one. When it reaches zero the send port’s predicate is false, the loop stops, and a null port subscribing on iOrders == 0 absorbs the final pass so nothing dead-letters for want of a subscriber.
var count = (JObject.Parse(input.Body)["orders"] as JArray)?.Count ?? 0; output.Variables["iOrders"] = count.ToString();
{{Message.MessageType}} == "InboundOrders" && {{Variable.iOrders}} > 0Open Variables, one assignment per row (select the variable, then enter the expression):
| Variable | Expression |
|---|---|
| idx | {{Variable.iOrders}} - 1 |
| current | {{Message.Body}}.JPath("$.orders[{{Variable.idx}}]") |
Bind the send port’s adapter parameter to {{Variable.current}}.
Close Variables, decrement the counter:
| Variable | Expression |
|---|---|
| iOrders | {{Variable.iOrders}} - 1 |
Everything body-related lives in the variable assignments. Newtonsoft's JSONPath accepts only a literal index, so the port computes idx first and the JPath resolves against a concrete $.orders[2]. And the adapter parameter is a plain string that never evaluates a body path, so Open Variables captures the element into Variable.current and the parameter binds {{Variable.current}}. The pass with the counter at 3 reads orders[2], the pass at 1 reads orders[0], every element exactly once, last-to-first. If processing order matters, capture the original count in a second variable at the receive port and assign idx ← {{Variable.total}} - {{Variable.iOrders}} to walk forward instead.
Keep the body light by not carrying the array in it. Capture the whole payload once into a held variable on the way in, the same technique the claim check uses, so the re-circulating message carries only the counter and the message type, never the body, and the send port reads each element out of the stored original.