B4.2 · dive 1 — the twenty-nine bytes
A cached name, a colon, and the writer's mint-time version.
EchoStore.Coherence.payload/2 frames two names and nothing else;
parse/1 refuses anything that is not exactly two valid branded ids. The committed surface
gate: a twenty-nine-byte payload of two names, parse refusing garbage. The cargo law of the whole
series — only identities cross — rides into coherence unchanged, and because the version is a branded id,
the whole conflict protocol is one comparison of payload bytes.
Source: content/bcs4.2.md, quoting bcs_rung_4_2_check.out; the module is
committed at runtimes/elixir/lib/echo_store/coherence.ex. This dive reads gates F1 and F2.
The transcript
bcs_rung_4_2_check.out · verbatim · this dive reads F1 and F2F1 surface ok -- the vocabulary is whole: channel, queue, a twenty-nine-byte payload of two names, parse refusing garbage; tables declare their lane in the directory; and the connector's push path refuses a protocol 2 connection with a typed :requires_resp3 F2 newer-wins ok -- a late stale invalidation bounced off both layers -- the L1 row survived holding px=105.00 and the L2 drop script answered 0 -- while a genuinely newer version applied and the replay of the old one stayed stale: idempotence is a comparison, not a log … (derive lines and gates F3–F6 elided; the full record is frozen on the module hub) PASS 6/6
The message and its vocabulary
content/bcs4.2.md · What · WhereThe frame is twenty-nine bytes: a cached name, a colon, and the writer's mint-time
version — two branded ids, one separator byte. parse/1 refuses anything that is not exactly
two valid branded ids, so garbage dies at the boundary, the same move the stores made at theirs. The rest
of the vocabulary derives from the table name and nothing else: the channel is
ecc:{<table>}:coh; the queue is ecc.coh.<table>; tables declare
their lane in the directory. And the connector grows the send-only push path the broadcast lane stands on
— push_command/3 and subscribe/2, nothing enqueued on the FIFO, RESP3 required
and refused otherwise with a typed :requires_resp3. A SUBSCRIBE confirmation arrives as a
push, so awaiting it on the FIFO starves the queue — the new verb sends without enqueueing an expectation,
and refuses protocol 2 where pushes and replies cannot share a wire.
The writer's side, after its store write — one call, either lane:
version = BrandedId.generate!("TXN") # the write's own identity
:ok = Table.put(:quotes, ast_id, "px=106.00", version)
{:ok, _heard} = Coherence.broadcast(conn, "quotes", ast_id, version)
# or, when at-least-once matters:
{:ok, :enqueued} = Coherence.enqueue(conn, "quotes", group, ast_id, version)
Mint versions where the write happens: the version is the write's identity, so the writer
who changed the store is the only true source of it — put/3 mints one for writers who have no
event id of their own, put/4 carries the writer's own.
Newer-wins has teeth
content/bcs4.2.md · What · HowThe dangerous case is not the fresh invalidation; it is the stale one arriving
late — a slow lane, a retry, a replay. The committed drill stages it: a row written at version
v_new, then an invalidation carrying an older version. The record: a late stale
invalidation bounced off both layers -- the L1 row survived holding px=105.00 and the L2 drop script
answered 0. The L1 side is one comparison in the owner; the L2 side is one Lua script — read the
framed version, compare payloads, delete only if newer — the same predicate in two places, because a late
invalidation that can erase a newer row is a coordination bug wearing a latency costume. And the same
comparison is the idempotence story: idempotence is a comparison, not a log — replaying a
version answers :stale the second time, with no dedup table anywhere.
Coherence.newer?("TXN0NuG2aaaaaaa", "TXN0NuFzzzzzzzz")
# payload bytes in mint order: true — no decode, no clock, no quorum
TXN versions — no decode, no clock, no quorum.Static result — newer?("TXN0NuG2aaaaaaa", "TXN0NuFzzzzzzzz") answers
true: payload byte G sorts after F, so the message applies.
Reversed, it answers false — the stale invalidation bounces off both layers. Replayed, the
comparison answers false again and the apply reports :stale — idempotence is a
comparison, not a log.
Why a comparison is enough: Valkey's own tracking sends an unversioned forget this
key; Nebulex synchronizes by deletion; neither message carries an order, so a late invalidation and a
fresh write race, and the loser is whoever applied last. The fix the literature reached in 1978 is a total
order constructed from timestamps, and this series has carried that order in every identity since Part I.
Two writes minted in the same millisecond on different nodes order by node-and-sequence bits — "an
arbitrary-but-total tiebreak in exactly Lamport's sense." The manuscript plans the measured face-off in
B4.5 · The Cache Referee; until that chapter ships, the comparison set is
characterized, never measured. The coherence: slot this message fills is declared by
B4.1 · Cache-Aside at ETS Speed's table directory.
Files: runtimes/elixir/lib/echo_store/coherence.ex, the grown
lib/echo_store/table.ex, the grown lib/echo_mq/connector.ex.
References
sources · relatedSources
- Valkey — Pub/Subthe lane the message rides; RESP3 push frames
- Valkey — Client-side cachingthe comparison set's deletion-shaped coherence: no version, no order
- Lamport — Time, Clocks, and the Ordering of Eventsthe 1978 total order; the arbitrary-but-total tiebreak
Related
- B4.2 — Coherence by Mint Timethe module hub; the full rung in context
- B4 — EchoStorethe chapter landing; Part IV's arc
- B3 — The Busthe wire and the connector the vocabulary grows on
- B2.2 — Property Stores on ETSthe boundary discipline parse repeats
- EchoMQ — the coursethe protocol in rung-level depth
- Redis Patterns Appliedthe substrate patterns
- Functional Programming in Elixirthe umbrella the runtimes live in