Skip to content

Documentation / @etherfold/processor-entities / bootstrapFromSnapshot

Function: bootstrapFromSnapshot() ​

bootstrapFromSnapshot(store, locations, options): Promise<BootstrapOutcome>

Defined in: packages/processor-entities/src/snapshot.ts:320

Bootstrap a store from the most advanced snapshot any of these locations has, unless the store is already further along.

ts
// `processorIdentity` is what the deployment's arrival derived and handed to its
// fold (ADR-0086), which is the one value naming this generation everywhere.
const store = await openSnapshotAware(await createBrowserStateStore(processor.entities));
const outcome = await bootstrapFromSnapshot(store, [
  'https://mirror-a.example/state.json',
  {url: 'https://mirror-b.example/state.json', head: 'https://mirror-b.example/head.json'},
], {processor: processorIdentity, finalityDepth: 64});

The behaviour is the free-form keeper's, point for point: every location is asked how far it has got, the furthest wins, an unreachable one is LOGGED and skipped rather than thrown, and local state that is already ahead is kept. Two differences, both deliberate:

  • Failover walks every remaining candidate, in descending order, where the free-form keeper tries the winner and then exactly one more (its own source says // TODO more than 2). With one mirror down and two up, this one gets state and that one does not.
  • A snapshot from another processor is not a candidate at all. The free-form keeper does not check, which is the gap processor-version-hash-cannot-silently-lie closed on the CLI's envelope. Here it is decisive rather than advisory, because a mismatch means the rows were computed by different logic.

Returning an OUTCOME rather than throwing on "nothing usable" is the same judgement the free-form path makes: not finding a snapshot is a normal first run in the wrong conditions, and the answer is to index from the start block. What DOES throw is a snapshot that was selected and then turned out to be unusable at install (SnapshotProcessorMismatchError, a document that breaks its own shape), because that is a publisher contradicting its own head.

The install streams ​

The winner's body is inflated and installed as it downloads, a block at a time (SnapshotAwareStateStore.bootstrap), so the whole document is never held. A download that fails PART-WAY therefore throws rather than failing over, because the install has started: for a snapshot without history that leaves only the floor marker over an empty store, and with history the floor and some later blocks with no cursor (it rides the last block). Either way the next boot (openAndBootstrap, which finds no cursor) bootstraps again, and the install replaces what the interrupted one left (SnapshotAwareStateStore.bootstrap).

A store that is behind is replaced, not caught up ​

A store whose own cursor is below the best candidate's takenAt is installed over, not only one that has never synced, and the install REPLACES whatever it computed itself (SnapshotAwareStateStore.bootstrap wipes it first, once the document's head and floor have been checked). Catching up from the local cursor instead would mean fetching the gap after a long absence, which is the historical eth_getLogs range a public node may refuse and exactly what a snapshot exists to avoid. A store at or ahead of every candidate is kept, untouched.

Parameters ​

store ​

SnapshotAwareStateStore

locations ​

SnapshotLocation | readonly SnapshotLocation[]

options ​

BootstrapOptions

Returns ​

Promise<BootstrapOutcome>