Bedrock.Cluster.Link.RoutingCache (bedrock v0.7.0)

View Source

The node-wide routing cache: which materializer covers a key range.

A partial, coalescing index of covering entries — FDB's DatabaseContext locationCache. Entries live until invalidated or dropped by a wiring push; staleness is backstopped by the client's retry loop, so there is no TTL.

It is an ETS table rather than server state because EVERY transaction on the node reads it, and reading it must not be a message. A cached lookup through the owning GenServer measured 0.79µs and flattened under concurrency; the same lookup here is 0.06µs and gets faster as readers are added (0.04µs at 16-way). One process is no longer a serialization point for the node's whole read path.

Writes still go through the Link, which owns the table: one writer keeps invalidation ordered against the pushes that trigger it, and the reply to a synchronous invalidate still means "the stale entries are gone".

The index is keyed by END key, so a lookup is a ceiling search — the smallest range ending after the key — and then a check that the range actually starts at or before it. Bedrock.end_of_keyspace/0 (<<0xFF, 0xFF>>) is the one INCLUSIVE end: it is the sentinel above every real key, not a boundary between ranges, so a key equal to it still belongs to the final range.

Summary

Functions

Drops every entry. The Link calls this on invalidation and on a wiring push.

Adds or replaces the covering entry for start_key..end_key.

The covering entry for key, or :not_cached.

Creates the table. Called by the Link, which owns it.

Types

entry()

@type entry() :: {Bedrock.key_range(), term()}

table()

@type table() :: atom()

Functions

clear(table)

@spec clear(table()) :: :ok

Drops every entry. The Link calls this on invalidation and on a wiring push.

insert(table, start_key, end_key, value)

@spec insert(table(), Bedrock.key(), Bedrock.key(), term()) :: :ok

Adds or replaces the covering entry for start_key..end_key.

lookup(table, key)

@spec lookup(table(), Bedrock.key()) :: {:ok, entry()} | :not_cached

The covering entry for key, or :not_cached.

Read directly by the calling process — no message to the Link.

new(table)

@spec new(table()) :: table()

Creates the table. Called by the Link, which owns it.

Public so any process on the node can READ without a message; readers never write. read_concurrency because the ratio is overwhelmingly reads — one write per cache miss, one read per key lookup.