Skip to content

Allow serving a pruned chain below deployed modules - #991

Merged
maoueh merged 15 commits into
developfrom
feature/truncating-store
Oct 15, 2026
Merged

maoueh merged 15 commits into
developfrom
feature/truncating-store

Conversation

@sduchesneau

@sduchesneau sduchesneau commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Lets an operator prune the chain (raise first-streamable-block above the initial block of deployed modules, mappers and stores alike) and keep serving every block that is still streamable.

With Tier1Config.AllowPrunedChain (forwarded to tier2 in ProcessRangeRequest.allow_pruned_chain):

  • A module whose initial block is below the first streamable block runs from that block on, instead of the request being refused. Module hashes don't change.
  • Store files keep the module's own initial block in their name (ex: 0400100000-0350000000.kv), so tier1 resumes from the snapshots written before the chain was pruned and tier2 keeps writing 0400101000-0350000000.kv, etc.
  • A request that needs a store starting below the first streamable block with no snapshot at the first streamable block is refused with InvalidArgument. The error names the store and says to set its initial block at or above the first streamable block, or to start the request where a later snapshot exists.
  • Requests starting below the first streamable block are still refused.
  • A request using a store without an initial block is refused (breaking for those modules on endpoints that enable the setting): such a store would be rebuilt from each new first streamable block while cached outputs still reflect its older state. The error asks for an initial block at or above the first streamable block.

Also fixed, with or without the setting, when the first streamable block is raised:

  • Stores without an initial block resumed from snapshots named after the previous first streamable block, then failed with snapshot "…" does not exist. Those snapshots are now ignored and the store is rebuilt.
  • In dev mode, the linear handoff could be rounded down below the first streamable block. It now stays at or above it.
  • The live back filler (after a quickload) could rewind below the first streamable block, or start from a snapshot it cannot load: that job failed, which stops the back filler for the rest of the request. It now starts at or above the first streamable block and skips those snapshots.

Limitations:

  • If the first streamable block is not a multiple of the state bundle size, store-dependent requests starting in that first partial segment are refused. (of course we will prune aligned on a boundary so this is a non-issue)

The firehose-core flag (--substreams-tier1-allow-pruned-chain) is in streamingfast/firehose-core#296.

@dfuse-bot

dfuse-bot commented Oct 13, 2026 •

Copy link
Copy Markdown

🔍 Vulnerabilities of ghcr.io/streamingfast/substreams:f070717

📦 Image Reference ghcr.io/streamingfast/substreams:f070717
digestsha256:f1b69c22ac9803cdf5766f0d1bc6401764375e98f6297da10dbcf7233c89d608
vulnerabilitiescritical: 0 high: 0 medium: 0 low: 0
platformlinux/amd64
size126 MB
packages380
📦 Base Image ubuntu:24.04
also known as
  • noble
  • noble-20260917
digestsha256:f610ab94648195aa356059f5b41d6085c9d4d903c072430cdd1af7bdb646106b
vulnerabilitiescritical: 0 high: 1 medium: 13 low: 7

With Tier1Config.AllowStoreTruncation, modules whose initial block is below the first
streamable block run from that block on, and their stores resume from snapshots taken
before the chain was truncated.
@sduchesneau
sduchesneau force-pushed the feature/truncating-store branch from 72a8acd to f306f4f Compare October 13, 2026 18:20
With the linear handoff at the first streamable block, tier1 planned no store
work and ran truncated stores from an empty state instead of their snapshot.
Stores without an initial block are named after the first streamable block, so
raising it made tier1 resume from snapshots that tier2 could not load.
Refused requests return before tier1's detached last_used and spkg writes finish,
so removing the test's temp dir failed now and then.
In dev mode, rounding the start block down to a segment boundary could land below
it, where tier1 would load a snapshot and stream blocks that no longer exist.
A failed job stops the back filler, and jobs below the first streamable block, or
starting from a snapshot named after another initial block, always fail.
Such a store is rebuilt from each new first streamable block while cached outputs
still reflect its older state, so tier1 now asks for an explicit initial block.
@sduchesneau
sduchesneau marked this pull request as ready for review October 13, 2026 20:52
@sduchesneau
sduchesneau requested a review from maoueh October 13, 2026 20:52

@maoueh maoueh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like AllowTailTruncation that would apply across the board, better error message for example.

Comment thread app/tier1.go Outdated
Comment thread orchestrator/plan/requestplan.go Outdated
Comment thread orchestrator/stage/fetchstorage_test.go
The setting covers mappers as well as stores. Error messages now name the truncated tail and say how to fix the request.
@sduchesneau sduchesneau changed the title Allow serving stores below first streamable block Allow tail truncation below deployed modules Oct 15, 2026
@sduchesneau
sduchesneau requested a review from maoueh October 15, 2026 12:32
A cursor replaces the start block, so a request with a cursor above the first streamable block was refused for a start block it did not use.
The start block was checked before the cursor was resolved on develop too, so the fix is part of this PR's changes.
@sduchesneau sduchesneau changed the title Allow tail truncation below deployed modules Allow serving a pruned chain below deployed modules Oct 15, 2026
@maoueh
maoueh merged commit 00bc09f into develop Oct 15, 2026
9 checks passed
@maoueh
maoueh deleted the feature/truncating-store branch October 15, 2026 15:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants