Skip to content

Documentation / @etherfold/core / GenerationRebuild

Class: GenerationRebuild<ABI, ProcessResultType> ​

Defined in: packages/core/src/generation/rebuild.ts:452

THE BOUNDED REBUILD OF ONE GENERATION: the chain-free, chunked counterpart of IndexerGeneration.followMore.

That one is a single unbounded advance driven by an engine that owns a provider; this one is a slice at a time, over a stream read through a port, on a runtime that has no chain at all. The RULES are shared and not restated: where a fold resumes is getFromBlock, what a stored stream becomes is generateStreamFromReplay, and what the raw rows decode to is LogEventFetcher.reparse.

It holds no position between calls, on purpose. Everything it needs is read at the top of more() from the processor's persisted cursor, so a fresh object graph -- a new process, a new isolate, a new container over the same database -- resumes exactly where the last committed chunk left off. A field remembering the last chunk would be the one thing a kill between two chunks could lose.

Type Parameters ​

ABI ​

ABI extends Abi

ProcessResultType ​

ProcessResultType = unknown

Constructors ​

Constructor ​

new GenerationRebuild<ABI, ProcessResultType>(processor, source, options): GenerationRebuild<ABI, ProcessResultType>

Defined in: packages/core/src/generation/rebuild.ts:468

Parameters ​

processor ​

EventProcessor<ABI, ProcessResultType>

source ​

IndexingSource<ABI>

options ​

GenerationRebuildOptions<ABI>

Returns ​

GenerationRebuild<ABI, ProcessResultType>

Properties ​

defaultFromBlock ​

readonly defaultFromBlock: number

Defined in: packages/core/src/generation/rebuild.ts:454

The earliest block this source can have anything to say about.


stream ​

readonly stream: string

Defined in: packages/core/src/generation/rebuild.ts:456

WHICH stream is folded, and the key every read of it carries.

Accessors ​

generation ​

Get Signature ​

get generation(): GenerationId

Defined in: packages/core/src/generation/rebuild.ts:489

WHICH generation this rebuilds: the stream above, plus the fold over it.

Returns ​

GenerationId

Methods ​

follow() ​

follow(delta): Promise<{ applied: boolean; replayed: number; }>

Defined in: packages/core/src/generation/rebuild.ts:688

TAKE THE DELTA THE STREAM'S WRITER JUST APPENDED, if this fold is level with it.

The live half of the same one advance. Under ADR-0087 the DEPLOYMENT fetches a stream and appends to it, and every generation over that stream READS what was appended -- so a fold sitting exactly where the append begins folds it there and then, instead of paying a round trip to read back rows it was just handed.

It is the SAME code path as more() below the read: the same checkpoint, the same reparse, the same generateStreamFromReplay, the same delivery cut. Only the source of the chunk differs -- the port, or the writer -- which is what keeps "a generation is a stream plus a fold over it" one implementation rather than two that agree on the day they were written.

Declining is the ordinary answer and never an error ​

A fold that is BEHIND the stream cannot apply a delta beginning above where it resumes: doing so would leave the blocks between as a HOLE in its own state. generateStreamFromReplay already refuses exactly that (UnexpectedFromBlockError), and the refusal is caught HERE and reported as declined rather than thrown, because it is not a fault: a successor mid-catch-up is behind BY DESIGN, and its bounded rebuild is what carries it. A fold that is AHEAD -- a delta it has already applied, re-offered -- resumes above it and declines for the same reason.

Nothing here is a hand-over of the write duty. The append already happened, positioned from the stream, before this fold was consulted; what a fold does or does not take changes nothing about what is stored.

Parameters ​

delta ​
eventStream ​

LogEvent<ABI>[]

lastSync ​

LastSync<ABI>

Returns ​

Promise<{ applied: boolean; replayed: number; }>


more() ​

more(options?): Promise<RebuildReport>

Defined in: packages/core/src/generation/rebuild.ts:519

ONE CHUNK: resume from the durable checkpoint, replay a bounded slice, and report.

The order is the whole of the resumability guarantee. The checkpoint is READ first, from the store, so nothing in this process decides where to resume. The slice is then applied through process, which writes the state and the cursor describing it in ONE transaction (ADR-0027), so the call either advanced both or neither. Nothing is written here afterwards: there is no second durable value that a crash could leave disagreeing with the state.

Nothing is CLEARED on any branch, unlike the load path, and for the reason readOnlyStream gives: this generation owns neither the stream it reads nor the cursor of whatever else wrote into a namespace it can see. An absent or unreadable stream costs one idle call and the next one asks again.

Parameters ​

options? ​
maxEmissions? ​

number

Returns ​

Promise<RebuildReport>