The event bus
A defer-and-deliver FIFO whose delivery order is load-bearing, whose handler reports whether it actually folded an event, and whose drain guard salvages the event a panic was holding.
Every venue event the execution core folds passes through one
queue: crates/vike-exec/src/bus.rs's EventBus. It is small, and its header states the one
property that makes it more than a VecDeque: defer-and-deliver. A publish appends to the
back of the FIFO; if a drain is already running the call returns and the event waits its turn;
otherwise the call drains, delivering each event in full before the next one starts. The ordering
is load-bearing rather than tidy — the example the header gives is a one-cancels-other bracket,
where the auto-cancel publishes OrderCanceled while OrderFilled is being delivered, and the
cancel must land after every subscriber has seen the fill.
One writer, one outbox
The single-writer core owns both the bus and its handler, so callback re-entrancy is impossible by
construction. Instead of publishing back into the bus mid-fold, a handler pushes follow-on events
into an Outbox, and the drain loop appends that outbox to the back of the same FIFO after the
fold returns. Follow-ons are therefore delivered after every already-queued event and never
recursively — byte-identical delivery order to the original semantics, and clean under the borrow
checker. The draining latch is kept as an explicit field even though the single-writer core can
never set it re-entrantly; the parity test's chained publisher exercises it, and the semantics stay
written down.
EventHandler is the bus's one subscriber type, and ExecutionEngine is the handler: its on_event
folds the venue stream through the order state machine and the account,
and — as crates/vike-exec/src/execution_engine/mod.rs's header says — it folds state only;
durable persistence belongs to the runtime's journal. Every
delivered event is also appended to the bus's delivered log, which the runtime takes each batch
and folds into its bounded recent-events ring — the seam the desktop app's event echo reads through
a lossy observer channel, and the seam the fixtures assert delivery order against.
The fold reports a verdict
on_event returns a Fold: Applied when the event actually changed state, Dropped when the
handler refused it — an unknown client-order-id, an illegal transition in the
order lifecycle, a reconnect replay, an event for a symbol or
venue this engine does not own, or a non-finite venue number. "Invalid transitions are dropped" is
a core law of the order management system, and the Fold doc records why the verdict had to become
visible: before it existed on_event returned nothing, so a downstream reaction keyed off the
event rather than off the fold's acceptance of it, and fired for events the engine had refused.
The live one-triggers-other / one-cancels-other drive was exactly that — a fabricated OrderFilled
on an unknown client-order-id cancelled its sibling and armed its held children even though the
engine had dropped the event and counted it into dropped_unknown_coid.
publish returns the verdict for the event it was handed. Follow-on events drained by the same
call carry their own verdicts, which are not reported: no caller reacts to them, and the site that
published them is the one that would. crates/vike-core/src/runtime/mod.rs's dispatch names the
consumer this exists for — the contingency drive on the venue
ingest lane is gated on the fold's verdict, because without that gate a fabricated fill on one
bracket leg cancels its sibling and leaves a position naked. The in-process client seam is
deliberately not gated.
The deferred branch answers Applied, and it is not for you
When publish finds a drain already running it returns Fold::Applied without knowing anything.
That branch is structurally unreachable in the single-writer core — draining can only be set by a
publish higher in the same call stack, and the engine publishes into its outbox rather than back
into the bus — so it exists only for the parity test's chained publisher, and answering Applied
there keeps that path byte-identical to its pre-verdict behaviour; answering Dropped would invent
a new way to orphan a legitimate bracket on a path nobody exercises. A caller that genuinely needs
the verdict of a deferred event must not use this seam.
What a panic mid-fold does
The drain is unwind-safe in the way a try/finally would be: a drop guard clears the draining
latch on the way out, so after the runtime's catch_unwind the next publish drains normally, with
every undelivered event still queued in order. The publish doc records the review finding that
put it there — without the guard, one in-drain panic would silently defer every later event
forever.
The same guard does a second job. The event being folded is held in an in_flight slot during
on_event; a clean return moves it into delivered, so anything still in the slot when the guard
drops was lost to a panic, and the guard pushes it into a poisoned list instead of letting it go.
The runtime drains take_poisoned after its catch_unwind fires and surfaces each as a lost
terminal in the recent-events ring, so a panic can never silently strand an order — the test
panic_mid_fold_salvages_the_in_flight_event pins that the salvaged event is recorded exactly once
and is not re-folded. This is the bus's half of the core's panic policy; the runtime's half is on
the execution core page.
Where the events come from
The bus consumes what the ingest lanes deliver — the lossless
EventSender every venue adapter holds pushes canonical events into the core's single ingest
channel, and the drain loop publishes each one here. The variants themselves, who emits each and
what the state machine does with it, are one page each under events.
Settings
One directory, five files split by who is allowed to change a value — and the risk ceilings have no environment layer at all, because a ceiling you can raise from a shell export is not a ceiling.
Ingest lanes
The producer-side channels every venue adapter holds — lossless where a missed message is a hole, latest-wins where only the freshest value matters — and why they live one crate below the core that drains them.