jonnify·bcs /bcs/cache/coherence-by-mint-time/the-twenty-nine-bytes

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 frame, anatomized. Two branded ids of fourteen bytes each and one separator — twenty-nine bytes on the wire. Select a part to read what it carries and what parse demands of it.
the cached name 14 bytes · a branded id · the row being invalidated : 1 byte the mint-time version 14 bytes · a branded id · the write's own identity 14 + 1 + 14 = 29 bytes · nothing else crosses
readout · Select a part of the frame. The payload is two names and one separator; everything the receiver does with it is one comparison of payload bytes — §3 stages that comparison live.
§1

The transcript

bcs_rung_4_2_check.out · verbatim · this dive reads F1 and F2
content/echo_data/runtimes/elixir/bcs_rung_4_2_check.out · verbatim · F1–F2; the record continues through F6 — the hub holds it wholefrozen
F1 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
§2

The message and its vocabulary

content/bcs4.2.md · What · Where

The 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.

§3

Newer-wins has teeth

content/bcs4.2.md · What · How

The 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
The comparison, run live. The manuscript's own version pair, compared three ways — the fresh write, the late stale invalidation, the replay. Each verdict is the same one-line predicate: payload bytes, byte order.
readout · Choose a case. The predicate strips the three-byte namespace and compares the payload bytes of the two 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.

§4

References

sources · related

Sources

Related