The Evicted arm is the engine's honesty about bounded retention.
Snapshot history is a ring buffer with a configurable cap; a read
for a time that falls outside the window cannot return a value,
and dressing that case up as undefined or throwing would force
every caller to invent the same handling. Returning a
discriminated union forces a tag check at the call site, the same
pattern used for Resource and Formula to make impossible
states unrepresentable.
oldestRetainedTime is a window boundary ONLY when retention is onThe clamp above terminates iff the graph opted into retention. Both
caps default to 0 (see
CreateCauslOptions.commitHistoryCap), and at cap 0 there is
no window, so oldestRetainedTime is not its lower edge: it
reports Graph.now, which is a placeholder meaning "the
earliest time you could hope for if you opted in from here", and
reading at it evicts too. So the obvious retry loop spins forever.
MEASURED on a default-cap graph after two commits:
graph.readAt(a, graph.now) // evicted { oldestRetainedTime: 2 }
graph.readAt(a, 2) // evicted { oldestRetainedTime: 2 }
graph.readAt(a, 2) // evicted { oldestRetainedTime: 2 } ...
Do not write the clamp as a loop that re-reads until it retains.
Either treat evicted as terminal, or decide from the caps the graph
was constructed with, which is the value a caller already holds:
const res = graph.readAt(node, t)
if (res.status === 'evicted') {
// Retry ONCE, and only if this graph has retention at all.
if (retentionIsOn && res.oldestRetainedTime > t) {
return graph.readAt(node, res.oldestRetainedTime)
}
return notAvailable
}
Result of Graph.readAt: either the value retained for the requested time, or an
evictedmarker carrying the oldest still- retained time so callers can clamp future requests into the window.