5.1. Causal Delivery Mailbox
A publish-subscribe system where the mailbox enforces causal ordering of messages (Sections 3.6 and 4.9 of the paper).
5.1.1. Engine Types
MailboxActors.Examples.CausalMailbox.PubSubIdx defines two engine
kinds:
-
relay— forwards messages between nodes, -
broker— delivers to local subscribers with causal ordering.
5.1.2. Message and State Types
A MailboxActors.Examples.CausalMailbox.TopicMsg carries:
-
publisher— the originating address, -
deps— aFinsetof message hashes representing causal dependencies, -
contentandsig— payload and signature, -
msgHash— the message's own hash for dependency tracking.
The broker's local state (MailboxActors.Examples.CausalMailbox.CausalState)
maintains three fields:
-
delivered— the set of hashes of already-delivered messages, -
pending— messages buffered because their dependencies are not yet met, -
ready— messages whose dependencies are satisfied and are ready for delivery.
5.1.3. Causal Guard and Action
The causal guard (MailboxActors.Examples.CausalMailbox.causalGuard)
always matches (its witness type is Unit). The real logic lives in the
action (MailboxActors.Examples.CausalMailbox.causalAction), which
branches on dependency satisfaction:
-
Dependencies met: the message is added to
ready, its hash is recorded indelivered, and a cascade check releases any pending messages whose dependencies are now satisfied. -
Dependencies not met: the message is buffered in
pending.
The resulting MailboxActors.Examples.CausalMailbox.causalBehaviour
is a WellFormedBehaviour — the single-guard list trivially satisfies
NonOverlappingGuards.
5.1.4. Correctness
The causal delivery invariant states that every message in the ready
list has its causal dependencies recorded in the delivered set.
The theorem MailboxActors.Examples.CausalMailbox.causalAction_preserves_invariant
proves that causalAction preserves this invariant: messages are only
released to subscribers when their causal predecessors have already been
delivered. The cascade step (via findCascade) also respects the invariant,
since findCascade only releases messages whose dependencies are a subset
of the updated delivered set.