B2.5 · dive 3 — traversal and coherence
Chronology, still free.
E4's two hundred edges come back forward 200 ascending with a 10-edge page head;
reverse finds all 50 holders, ascending — and the ascending order is worth a sentence beyond
correctness: tuple keys compare element-wise in term order, so within one subject the objects sort by
their own bytes — which, by Chapter 1.2's theorem, is mint order. A portfolio's forward traversal
is its acquisition timeline, free.
Source: content/bcs2.5.md, quoting bcs_rung_2_5_check.out; the system is
committed at runtimes/elixir/lib/echo_data/bcs/edge_store.ex.
unlink moves it to where E5 ends.The transcript
bcs_rung_2_5_check.out · verbatim · this dive reads E4 and E5boot: the holds relation is its own system -- PRT subjects, AST objects, indexes private E1 surface ok -- the relation's surface: link, unlink, props, from, to, degree -- and its indexes are nobody's business E2 gates ok -- both ends gated: subject must be PRT, object must be AST -- {:error, :namespace} on either violation E3 retire ok -- the interim representation retired: positions struck out of the balance row and copied down as edges -- the 2.2 label is paid E4 traverse ok -- forward 200 ascending with a 10-edge page head; reverse finds all 50 holders, ascending E5 unlink ok -- unlink removes both directions atomically: degree 199; the reverse index no longer lists the subject PASS 5/5
E4 — traversal rides the order theorem
content/bcs2.5.md · What · HowForward traversal is a three-line match spec over the tuple keyspace, ascending by the table's own term order:
spec = [{{{s, :"$1"}, :"$2"}, [], [{{:"$1", :"$2"}}]}]
{:reply, {:ok, take(st.fwd, spec, limit)}, st}
Tuple keys compare element-wise in term order, so within one subject the objects sort by their own bytes — which, by Chapter 1.2's theorem, is mint order. A portfolio's forward traversal is its acquisition timeline, free, because the keys never stopped being chronology. The theorem itself is Part I's — B1, Ideas Behind the System — and this rung rides it into relations without adding a column or a clock.
In Go, fixed width pays again: a composite key is the two names concatenated — twenty-eight bytes, always — and a subject's range is a prefix scan over a sorted slice:
key := subj + obj // 28 fixed bytes, no separator needed i := sort.SearchStrings(fwd, subj) // first edge of the subject j := sort.SearchStrings(fwd, subj+"\xff") edges := fwd[i:j] // ascending objects: the acquisition timeline
The reverse slice mirrors it with obj + subj, both owned by the one
goroutine from Chapter 1.1, both invisible outside the package.
E5 — coherence under one owner
content/bcs2.5.md · What · Decisions · BoundariesE5 unlinks one edge and gates both directions at once: degree 199; the reverse
index no longer lists the subject. The dual indexes stay coherent because exactly one process
writes them, in one callback — the part's ownership law doing consistency work that would otherwise need
a transaction.
One design trade is made explicitly: props are written into both indexes, so a reverse read is one hop. Two writes per link, atomic enough because one process performs both; if edge props ever grow heavy, the reverse index drops to keys-only and the owner joins internally — the alternative is stated here so the future diff is a decision, not a discovery.
link and
unlink against the two private indexes. Select an operation; the readout shows both
indexes after the callback returns.Static states — link: forward gains
{subject, object} → props, reverse gains {object, subject} → props
— two writes, one owner, one callback · unlink: both entries leave in the same
callback — unlink removes both directions atomically · keys-only alternative: the
reverse index holds keys without props, a reverse read joins internally through the owner — the
pre-stated trade for the day props grow heavy.
Boundaries, taught honestly: one relation kind per store — a second relation is a second
system, not a kind column. Edge windows (object-id cursors over one subject's range) are the
natural next export and wait for their review gate rather than riding in here. No cardinality limits are
enforced; a million-edge subject pages but its from/2, :all is a million-tuple reply, which
is the caller's choice to make. Single node, one writer, as the part prescribes.
References
sources · relatedSources
- Codd, E. F. — A Relational Model of Data for Large Shared Data Banksrelations as first-class; the model the traversals read
- Erlang/OTP — the ets moduleordered_set term-order traversal over tuple keys; match specifications
Related
- B2.5 — Relations Are Systemsthe module hub; the full rung in context
- B1 — Ideas Behind the Systemthe order theorem the traversal rides
- B2 — The Elixir BCS Corethe chapter landing; the Part II arc
- Functional Programming in Elixirthe umbrella where echo_data lives