B8.1 · dive 1 — the Disruptor seat
Admission as a typed answer at the door.
The ingress half of the engine answers one question: in what order, and at what cost of
admission. EchoCache.Ring is the seat — real, shipped Elixir at
echo/apps/echo_cache/lib/echo_cache/ring.ex, a bounded buffer whose publish/2
answers :ok or :dropped with the drop counted, drained by exactly one process.
Admission control is a typed answer at the door rather than an incident discovered as latency. The committed
gate fixes the shape: 64 accepted, 136 refused with :dropped and counted — never blocked, never
overwritten.
Source: the Ring is real umbrella source at
echo/apps/echo_cache/lib/echo_cache/ring.ex, actively hardened by the rung-gated EchoMQ program
(docs/echo_mq/emq.roadmap.md); its behavior is also on the committed B4.3 record
(bcs_rung_4_3_check.out, PASS 6/6). The drainer in front of it,
Exchange.Book — the trading engine on top — is PROPOSED (docs/trading/),
taught as design because it has run no rung, never the substrate.
:ok until the ring is full, then :dropped with a
running count; release the held applier to drain. Every readout line is the structure's own
arithmetic.The pattern, at its source
docs/trading/trading.patterns.md · Fowler · the Disruptor paperLMAX's published architecture centers a Business Logic Processor that runs entirely in memory by event sourcing and handles "6 million orders per second on a single thread" (Fowler), surrounded by Disruptors — pre-allocated ring buffers where producers claim slots, a single writer applies in batches, and consumers chase sequence numbers without locks. The team's reported conclusion is the part that generalizes: contended queues are at odds with how modern CPUs run, and the cure is the single-writer principle plus mechanical sympathy — one owner per mutable thing, batch when behind, make waiting policy explicit.
The 6-million figure is external, and it is quoted with its attribution. It is not a number
the trading engine claims; the Exchange.* suite on top of the Ring has run no rung yet. The Ring
itself is real and measured — its numbers are on the B4.3 record. The engine takes the principles, not the
count.
What transfers, and what does not
docs/trading/trading.patterns.md · the design's reasoningThe BEAM cannot and should not imitate the Java mechanics — and does not need to, because the principles transfer without them. Select an element to read why it transfers whole or why the BEAM deliberately drops it.
| LMAX element | Verdict | Why |
|---|---|---|
| bounded buffer + overload answer | transfers whole | the Ring's publish/2 answers :ok or :dropped, the drop counted |
| single writer, batched applies | transfers whole | one drainer per book, woken to apply whole batches in arrival order |
| sequence as coordination | transfers whole | the sequence is the branded Snowflake stamped at admission — one ordering for all |
| journaling beside the hot path | transfers whole | recovery is replay over the log — the next module's subject |
| busy-spin wait strategies | does not transfer | scheduler-hostile on the BEAM; the Ring parks and the wake is a message |
| cache-line padding / slot pre-alloc across heaps | does not transfer | the win evaporates across heap boundaries; the BEAM's copying isolation is already paid |
| multi-consumer barriers on the hot buffer | does not transfer | downstream consumers read the log, never the ingress buffer — the Ring stays a seat, not a bus |
The seat is exact, not analogical
echo/apps/echo_cache/lib/echo_cache/ring.ex · B4.3 recordThe seat is real source, and it matches the pattern part for part. The moduledoc names the
correspondence in the house's own words (source:
echo/apps/echo_cache/lib/echo_cache/ring.ex): "This is the Disruptor's shape translated to the
BEAM — sequences, preallocated slots, batched consumption — standing beside the bus's park-don't-poll: both
replace discovery with arrival," and "the single-producer requirement is structural, not advisory." The
committed B4.3 record carries the shape in numbers — the bound, the gauge, the batch-shaped drain — every
figure verbatim from the ring's own rung:
G4 full ok -- the bound held its shape: 64 accepted, 136 refused with :dropped and counted -- never blocked, never overwritten -- then the release drained all 64 and publish 201 landed and applied: a storm bends the lane's at-most-once contract no further than the contract already bends G3 occupancy ok -- mid-storm the gauge read 600 of 4096 and drained to exactly 0; priced, the ring moved 100000 items in 99 ms -- 1005116 items per second end to end on one scheduler, inside the derived band, largest batch 200, nothing dropped G1 surface ok -- the ring's surface is whole -- publish, occupancy, stats, stop, a generic one-batch apply function -- ... a fresh ring stands at occupancy 0 PASS 6/6
The bound is real: 64 accepted, 136 refused with :dropped and counted, then
the release drains all 64 and the next publish lands. The gauge is observable:
mid-storm the gauge read 600 of 4096 and drained to exactly 0. The drain is single-consumer and
batch-shaped, with the largest batch a reported stat: largest batch 200, nothing dropped. The
ring under storm refuses, recovers, and keeps serving — exactly the admission contract a match path needs.
The Exchange.Book that drains it is PROPOSED: the single writer, woken to drain whole
batches, shelling out to a pure Decider — the trading engine on top of a real, hardened substrate, taught as
design because it has run no rung, and so it claims no number; the Ring beneath it is shipped and
measured.
The chase sequence is the id
docs/trading/trading.specs.md · the order theoremThe one twist this house adds to the pattern: the chase sequence is not a slot counter
beside the data but the branded Snowflake inside it. Mint order is the sequence, so a consumer's
resume cursor is an id — EchoData.BrandedTree.page_after/4 reads strictly after it in creation
order — the same order holds in every store by the byte-sort theorem, and there is no second numbering scheme
to reconcile with the first. A counter beside the data is a second source of truth; the id is the first one,
already paid for at mint.
The alternatives are named honestly. The unbounded GenServer mailbox — the BEAM
default and the proper baseline: it preserves order and the single writer for free; what it lacks is an
admission answer, so overload arrives as mailbox depth, which arrives as latency. The Ring's
:dropped is the same architecture with the truth told at the door. GenStage / Broadway —
demand-driven pull is the right shape where the consumer sets the pace (draining work), and the wrong shape
at market ingress, where producers are external and the answer must be immediate accept-or-shed. A stream
as the ingress (XADD first, decide later) — durable and replayable, but one wire round trip before every
decision, and it logs commands, not facts, re-opening the command-sourcing coupling the next dive names.
Where the seat is the wrong tool, stated: low-rate aggregates — an admin book, a reference-data writer — gain nothing from a Ring over a plain call; fan-out is never the Ring's job (one drainer, by law); and durability is never the Ring's job either — the Ring may drop by design, the log may not lose by design, and the two truths are different and both stated. The pure core that reads what an accepted command means is B8.1.2 · The Decider.
References
sources · relatedSources
- Fowler — The LMAX Architecturethe Business Logic Processor, the single-thread figure quoted here, the case against contended queues
- The LMAX Disruptor (technical paper)the bounded ring, sequences, batching, wait strategies — the pattern the as-built Ring fills
- Chassaing — Functional Event Sourcing Deciderthe fact-vs-command distinction the stream-as-ingress alternative trips on
Related
- B8.1 — The Enginethe module hub; the full ring record in context
- B4.3 — The Single Writer and the Ringthe as-built ring this dive quotes, in its home chapter
- B4 — EchoCachethe chapter the ring lives in
- B3 — The Busthe log downstream consumers read instead of the ring
- Redis Patterns Appliedthe bounded-ring substrate
- EchoMQ — the coursethe bus protocol in rung-level depth