erigontech / erigontech/erigon
db/kv, db/state: add an additive RangeReader interface and fold in the harness range machinery
- Dominant language
- Go
- Stars
- 3.6k
- Forks
- 1.5k
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 455
Description
## Motivation
#22467 introduced `membatchwithdb.DomainReader` — an overlay→SharedDomains bridge for **point** domain reads (`GetAsOf`, `HistorySeek`), wired via `overlay.DomainReader = sd`. It's the clean mechanism for making overlay read views observe in-flight (not-yet-committed) tip state.
#21414 converged on `DomainReader` for point reads, but it still carries a **separate** in-memory range/history/index machinery for the RPC test harness, because `DomainReader` does not cover those methods:
- `SharedDomains.RangeAsOf` / `HistoryRange` / `IndexRange` (+ `TemporalMemBatch` helpers: `memRangeAsOf`, `memHistoryRange`, `memIndexTxNums`, `iiMem`, `liveLimitKV`, …)
- the harness `OverlayDB` / `sdRoTx` wrapper that routes RPC reads through those.
So today there are two overlapping overlay-read mechanisms: `DomainReader` (point reads) and the harness range machinery (range/history/index).
## Proposal — additive `RangeReader`, not a fattened `DomainReader`
Keep `DomainReader` focused on point reads and add a **separate, additive** interface for the range/history/index surface (interface segregation — a consumer implements only what it serves):
```go
type RangeReader interface {
RangeAsOf(ctx, domain, fromKey, toKey, ts, asc, limit, roTx) (stream.KV, error)
HistoryRange(ctx, domain, fromTs, toTs, asc, limit, roTx) (stream.KV, error)
IndexRange(name, k, fromTs, toTs, asc, limit, roTx) (stream.U64, error)
}
```
- `MemoryMutation` gains an optional `RangeReader` field alongside `DomainReader`; `overlay.RangeReader = sd` wires the SD (which already implements these).
- The overlay/read-view range methods route through `RangeReader` when set, exactly as point reads route through `DomainReader`.
- (Latest reads `GetLatest`/`HasPrefix` can join `DomainReader` or a small `LatestReader` — decide when wiring.)
Then the harness `OverlayDB`/`sdRoTx` and the standalone `SharedDomains.RangeAsOf`/`HistoryRange`/`IndexRange` delegations fold into the `RangeReader` path, removing the duplicate mechanism. `DomainReader` stays small; nothing that only needs point reads has to grow.
## Scope / sequencing
Do this alongside (or after) the bg-commit-default flip, where in-flight range reads actually matter. Until then #21414 keeps the range machinery as-is. Relates to #21414 (converged on `DomainReader` for point reads), #22467 (introduced `DomainReader`), #22520 (SD run-task worker), #21314 (SD-aware consumers).
Contributor guide
Research direction
Start with MemoryMutation and DomainReader, then trace SharedDomains.RangeAsOf, HistoryRange, and IndexRange through the overlay/read-view paths. Inspect the harness OverlayDB and sdRoTx wrappers to understand the duplicate range machinery. Done means range, history, and index reads use the optional RangeReader path while DomainReader remains focused on point reads.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend-api-design, databases
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100