Ports and links
Understanding ports is understanding when a box runs. This page is the model’s reference.
The three implicit ports
Section titled “The three implicit ports”Every box has them, without their appearing in its configuration:
| Port | Direction | Flow | Role |
|---|---|---|---|
in | Input | Signal | Trigger. Several incoming links accepted |
error | Output | Value + signal | Failure route |
done | Output | Signal | Emitted once the box and its whole downstream subgraph have completed |
Three boxes have no error port: Output, Now and Retry (the last of
which is itself an error boundary). Two have no done: Output and Throw.
Flow types
Section titled “Flow types”| Flow | Mental symbol | Behaviour |
|---|---|---|
| Value | A piece of data | Carries a value; also serves as a trigger |
| Signal | A tick | Carries nothing, only triggers |
| Both | Carries a value and triggers |
The one forbidden combination: a pure-signal output into a pure-value input. There would be nothing to put in the value.
Data types
Section titled “Data types”any · json · number · string · boolean · duration · response ·
status · list · object.
Typing serves mainly for visual comfort, with one strict exception: a list
input (the list port of the Add to a list and Remove from a list actions)
refuses a source that is not list-compatible. json and list are compatible
with each other; a plain object is not.
- An input port accepts only one link. That is what keeps the graph readable: one value, one origin.
- Except
in, which accepts as many links as you like. - An output can feed as many inputs as you like.
When a box runs
Section titled “When a box runs”Three rules, in order:
- Roots start. Any box with no incoming link is primed when the scenario is launched. There is no “start” box.
- Only wired inputs are awaited. A box runs when each of its input ports that is actually connected has received a value. An unwired port is never awaited. Values are remembered: an input keeps the last value it received.
- The
inport acts as a barrier. Fed by several links, it waits for all of them to have arrived, then triggers once. That is the model’s “wait for these three branches to finish”.
The exception: replaying on every event
Section titled “The exception: replaying on every event”The “Play on each event received” option (in the box’s context menu) turns every wired input into a non-blocking “or” gate: the box re-triggers on every value received, on any port.
Two uses: handling a stream message by message, and unblocking a completion cycle (a graph that loops back on itself).
done versus a value output
Section titled “done versus a value output”This is the most useful distinction in practice:
- a value output emits as soon as the box has produced its result;
doneadditionally waits for everything that consumes that result to have finished.
To sequence — “do all this, then clean up” — wire from done. To pass data, wire
from the value output.
Conditional branches
Section titled “Conditional branches”They are not a separate mechanism: they are output ports carrying a role, which drives their colour.
| Box | Outputs |
|---|---|
| If | then / else |
| While, Do…While | then (the body) |
| Assert | then (success) / else (failure) |
| Retry | attempt / exhausted |
| Schema validate | valid / invalid / errors |
| Switch | one port per case, plus default |
| Socket.IO connect | one port per declared event, plus others |
Link selectors
Section titled “Link selectors”A link can carry a selector: a path applied to the value in transit.
data.items[0].idbody['user-id']headers["content-type"]statusThe a.b, a[0], a['key'] and a["key"] forms are accepted. A segment
holding JSON is parsed on the fly; a path that matches nothing yields
undefined.
Restorm sometimes infers a selector on its own at wiring time, when the source has a static preview that reduces to a single primitive value. You can always replace it or empty it.