Connections
A connection is more than an arrow on the canvas — it is a contract between an active and a passive component, and it is where queueing behaviour actually comes from.
Push and pull#
Every connection has an active side and a passive side. A Generator pushes: it decides when an entity exists and hands it downstream. A Server pulls: it asks its source for work, and once the work is done it pushes the finished entity onward. A Queue is passive — it never acts on its own, it only answers the components attached to it.
That is why Generator → Queue → Server is the shape everything is built from: an active component on each end, with the passive buffer in the middle absorbing the difference in pace. Connecting two active components directly leaves nowhere for the mismatch to go.
Waiting and timeouts#
Neither side gives up the instant the other is not ready. A push into a full queue waits for space; a pull from an empty queue waits for an entity. As soon as the situation changes the waiting request is served — an entity arriving at a queue where a server is already waiting is handed straight over, without ever being stored.
Only when the wait runs out is the request answered with a failure, and the two sides treat that differently. A producer whose push timed out counts the entity as rejected and the entity leaves the model as dropped — this is the loss that shows up on a generator's or server's entity rate chart. A consumer whose pull timed out simply asks again; an idle server loses nothing by waiting.
Waiting is the mechanism behind back-pressure. When a downstream queue fills, the server in front of it cannot deliver what it has just finished, so it goes blocked and stops taking new work — which fills the queue behind it, which eventually pushes rejections all the way back to the generator.
Multiple connections#
A component may have more than one connection on either side. Outgoing connections are served round-robin, so entities are spread evenly across the downstream branches rather than favouring one; incoming connections are polled round-robin in the same way, so a server drawing from two queues alternates between them.
Round-robin distributes turns, not load. Two branches with different service rates each receive half the entities, and the slower branch is the one that backs up — which is often exactly the effect you want to demonstrate.
When a Generator or Server has no outgoing connection at all, entities leaving it are counted as completed and exit the model. That makes the last server in a chain a natural exit point — there is no separate sink component to place.
Wiring rules#
A model has to be wired up before it can run. The simulator checks these rules when you press play, highlights any component that breaks one, and explains what is missing:
- A Generator must have an outgoing connection — it has nowhere to put entities otherwise.
- A Queue must have an incoming connection — nothing would ever fill it.
- A Server must have an incoming connection — it has nothing to pull from otherwise.
Outgoing connections are optional. On a server, an unconnected output is a legitimate exit from the model — entities that leave it count as completed. A queue with no outgoing connection is accepted too, but nothing will ever drain it, so it fills to capacity and blocks whatever feeds it.