Skip to content

Implement cold-start chunk probing for faster query range heuristic - #1337

Merged
DZakh merged 4 commits into
mainfrom
claude/clever-clarke-yphfk8
Jun 19, 2026
Merged

Implement cold-start chunk probing for faster query range heuristic#1337
DZakh merged 4 commits into
mainfrom
claude/clever-clarke-yphfk8

Conversation

@DZakh

@DZakh DZakh commented Jun 19, 2026

Copy link
Copy Markdown
Member

Summary

Implements a cold-start probing strategy for chunked queries to quickly refresh the query range heuristic before committing to full-size chunks. When no earlier queries are in flight, the first two chunks use a smaller 0.9x probe size instead of the full 1.8x size, allowing their responses to return faster and inform better chunking decisions.

Key Changes

  • FetchState.res: Modified pushQueriesForRange to accept a hasEarlierPending parameter that controls chunk sizing:

    • When hasEarlierPending=false (cold start), first two chunks use 0.9x probe size
    • Subsequent chunks use full 1.8x size
    • Updated callers to pass hasEarlierPending based on whether pending queries exist
    • Extended chunking loop to handle up to 3 chunks instead of fixed 2
  • Test updates: Updated test expectations across multiple test files to reflect the new chunking behavior:

    • Rollback tests now expect probe-sized chunks (e.g., 107-109, 110-112) followed by full-size chunks (113-118)
    • Block hash queries include additional block numbers from the probe chunks
    • Gap-fill and continuation queries adjusted to account for the new chunk boundaries
    • FetchState unit tests updated to verify the smaller probe chunk sizes and their impact on query range heuristics

Implementation Details

The change introduces a heuristic optimization: when starting fresh (no in-flight queries ahead), smaller probe chunks allow responses to arrive quickly, enabling the system to measure actual query performance and adjust chunking strategy before committing to larger chunks. This is particularly beneficial for cold starts where the query range heuristic may be inaccurate.

The hasEarlierPending flag is computed at call sites:

  • When processing gaps before pending queries: hasEarlierPending=pqIdx.contents > 0
  • When processing the main range: hasEarlierPending=p.mutPendingQueries->Array.length > 0

https://claude.ai/code/session_01V2oe4wzvNM4P2RZEVFhDww

Summary by CodeRabbit

  • Bug Fixes

    • Improved adaptive query chunking with cold-start “probe” chunks, yielding more granular contiguous chunk queries when within limits.
    • Enhanced correctness for out-of-order chunk completion and chain reorganization scenarios, including rollback and partition-merge fetching behavior.
  • Tests

    • Updated E2E and unit test expectations for the new chunking heuristic, query ordering, and revised rollback/merge range and readiness behavior.

A single partition could not saturate its concurrency budget because each
scheduling round only ever produced 2 tail chunks. Emit up to 3 chunks per
range, and when no queries are in flight ahead of the range, size the first
two at 0.9x the history range so their responses return quickly and refresh
the chunking heuristic before committing to full-size chunks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V2oe4wzvNM4P2RZEVFhDww
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 71e2322d-e08e-445c-aa39-d5d140000901

📥 Commits

Reviewing files that changed from the base of the PR and between d6fe8f2 and fe0a8d4.

📒 Files selected for processing (3)
  • packages/envio/src/FetchState.res
  • scenarios/test_codegen/test/E2E_test.res
  • scenarios/test_codegen/test/rollback/Rollback_test.res

📝 Walkthrough

Walkthrough

pushQueriesForRange replaces its fixed 1-or-2-chunk logic with an iterative loop emitting up to 5 contiguous chunks using a 0.9-probe heuristic for the first two chunks, then full-size chunks. The make function uses shorthand notation for maxOnBlockBufferSize. Unit, E2E, and rollback tests are updated to match the new chunk boundaries and probe sizes.

Changes

Adaptive chunk probe heuristic

Layer / File(s) Summary
pushQueriesForRange adaptive chunking logic and shorthand updates
packages/envio/src/FetchState.res
Replaces the 1-or-2-chunk conditional with a loop emitting up to 5 contiguous chunks (2 probe + up to 3 full-size), computing a smaller 0.9-probe first chunk size and stopping when the next chunk exceeds maxBlock. Updates make to use shorthand for maxOnBlockBufferSize in both the appendOnBlockItems call and fetchState record initialization.
FetchState unit test: stale and parallel chunk range assertions
scenarios/test_codegen/test/lib_tests/FetchState_test.res
Updates the parallel-chunk stale-query test to use fromBlock values derived from the new 0.9-probe size, rewires the later-chunk (B) response simulation with updated latestFetchedBlock timing, and adjusts prevQueryRange, prevPrevQueryRange, and latestBlockRangeUpdateBlock assertions for both the later-chunk and stale-earlier-chunk responses.
E2E tests: partition chunking, ordering, and merge expectations
scenarios/test_codegen/test/E2E_test.res
Updates "partition queries adjust ranges" test to expect two 0.9-probe chunks followed by full-size chunks, changes shrink expectations to 90-size probe, revises out-of-order chunk resolution to resolve chunk3 first and identify chunk2 as the bridging query at fromBlock 1071, updates final DB assertion for item-1500 to source from chunk3, and expands DC2 and merged partition "4" query lists to reflect five total chunk ranges.
Rollback tests: chunk probe boundaries, gap-fill queries, and refetch ranges
scenarios/test_codegen/test/rollback/Rollback_test.res
Adjusts multichain rollback chunk toBlock boundaries (Some(111)→Some(108)) and block hashes accordingly, reworks "no duplicate queries" test to expect three initial chunks with a same-partition gap-fill, adds block 109 to getBlockHashesCalls, strengthens "efficient refetch after rollback" test to expect three specific ranges with partial resolution, updates rollback trigger logic to resolve post-reorg calls, and expands in-flight flush test to expect multi-probe sequences.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant pushQueriesForRange
    participant queryLoop
    participant BlockRange

    Client->>pushQueriesForRange: invoke with chunkRange, maxBlock
    pushQueriesForRange->>pushQueriesForRange: probeSize = 0.9 * chunkRange
    pushQueriesForRange->>queryLoop: emit probe chunk 1
    queryLoop->>BlockRange: create query with probe size
    BlockRange-->>queryLoop: chunk 1 query
    queryLoop->>queryLoop: emit probe chunk 2
    queryLoop->>BlockRange: create query with probe size
    BlockRange-->>queryLoop: chunk 2 query
    queryLoop->>queryLoop: loop: emit full-size chunks
    loop Full-size chunk iteration
        queryLoop->>BlockRange: check if next chunk fits within maxBlock
        alt fits
            queryLoop->>BlockRange: create full-size chunk query
            BlockRange-->>queryLoop: chunk query
        else exceeds maxBlock
            queryLoop->>queryLoop: break loop
        end
    end
    queryLoop-->>pushQueriesForRange: all chunk queries emitted
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • enviodev/hyperindex#1289: Both PRs update packages/envio/src/FetchState.res's make function initialization, including changes to appendOnBlockItems argument handling and buffer setup shorthand notation.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Implement cold-start chunk probing for faster query range heuristic' directly and specifically describes the main change: implementing an optimized cold-start chunk probing strategy for faster query range updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Adjust the chunk-boundary, growth/shrink, out-of-order, and partition-merge
assertions to the new cold-start probe sizing (two 0.9x chunks then full 1.8x)
and up-to-3 chunks per range.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V2oe4wzvNM4P2RZEVFhDww

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scenarios/test_codegen/test/rollback/Rollback_test.res (1)

2503-2532: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Trigger the reorg on the post-118 call instead of the first pending call.

Line 2505 intentionally leaves chunk2 (110-112) in flight, so the later resolveGetItemsOrThrow(..., ~resolveAt=#first) can resolve that earlier pending call while injecting prevRangeLastBlock=118. That pairs an impossible previous-block value with the 110-112 query and makes the rollback path depend on mock queue ordering. Resolve the specific pending call whose range starts after 118, or resolve chunk2 first and update the expected gap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scenarios/test_codegen/test/rollback/Rollback_test.res` around lines 2503 -
2532, The issue is that sourceMock.resolveGetItemsOrThrow with ~resolveAt=`#first`
is resolving the first pending call in the queue (chunk2 with range 110-112) but
pairing it with an impossible prevRangeLastBlock of 118. Instead of using
~resolveAt=`#first` to resolve the first pending call, find and resolve the
specific pending call whose fromBlock range starts after 118 (similar to how the
continuationCall was found earlier in the test by matching
call.payload["fromBlock"] == 116), or alternatively resolve chunk2 explicitly
first and update the test expectations accordingly. This ensures the reorg
checkpoint is paired with the correct query based on block ranges rather than
mock queue ordering.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scenarios/test_codegen/test/rollback/Rollback_test.res`:
- Around line 2395-2402: The test uses Array.some to verify the gap-fill query
exists for the 116-118 range in partition "0", but Array.some only checks for
presence of at least one matching query and cannot detect duplicates. Replace
the Array.some call that checks for the fromBlock == 116 && toBlock == Some(118)
condition with a filter operation that counts exact matches, then verify the
length equals 1 to ensure the gap-fill query is unique and not duplicated across
partition "0".

---

Outside diff comments:
In `@scenarios/test_codegen/test/rollback/Rollback_test.res`:
- Around line 2503-2532: The issue is that sourceMock.resolveGetItemsOrThrow
with ~resolveAt=`#first` is resolving the first pending call in the queue (chunk2
with range 110-112) but pairing it with an impossible prevRangeLastBlock of 118.
Instead of using ~resolveAt=`#first` to resolve the first pending call, find and
resolve the specific pending call whose fromBlock range starts after 118
(similar to how the continuationCall was found earlier in the test by matching
call.payload["fromBlock"] == 116), or alternatively resolve chunk2 explicitly
first and update the test expectations accordingly. This ensures the reorg
checkpoint is paired with the correct query based on block ranges rather than
mock queue ordering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 139035c0-39e1-49bd-9dba-72b549ee08f2

📥 Commits

Reviewing files that changed from the base of the PR and between 9640bc8 and abca271.

📒 Files selected for processing (4)
  • packages/envio/src/FetchState.res
  • scenarios/test_codegen/test/E2E_test.res
  • scenarios/test_codegen/test/lib_tests/FetchState_test.res
  • scenarios/test_codegen/test/rollback/Rollback_test.res

Comment thread scenarios/test_codegen/test/rollback/Rollback_test.res Outdated
- Assert the gap-fill query is unique (exactly one 116-118 in partition 0)
  instead of merely present, restoring the no-duplicate-queries guard.
- Trigger the reorg on the post-118 tail query so prevRangeLastBlock=118 is
  paired with its real parent block rather than an unrelated in-flight call.
- Drop an unused chunk binding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V2oe4wzvNM4P2RZEVFhDww
Emit two 0.9-size probe chunks followed by three full-size chunks on every
range, dropping the hasEarlierPending conditional. This keeps a single
partition's in-flight depth closer to what the pre-refactor twice-triggered
fetch produced, while still leading with fast probes that refresh the
chunking heuristic.

Update unit, E2E, and rollback test expectations for the new chunk counts
and boundaries.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V2oe4wzvNM4P2RZEVFhDww
@DZakh
DZakh merged commit 7973af4 into main Jun 19, 2026
8 checks passed
@DZakh
DZakh deleted the claude/clever-clarke-yphfk8 branch June 19, 2026 13:40
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.

2 participants