Skip to content

feat(indexer): add instant_receipts to IndexerChunkView#15465

Merged
pugachAG merged 2 commits into
masterfrom
feat/indexer-instant-receipts
Mar 27, 2026
Merged

feat(indexer): add instant_receipts to IndexerChunkView#15465
pugachAG merged 2 commits into
masterfrom
feat/indexer-instant-receipts

Conversation

@pugachAG

@pugachAG pugachAG commented Mar 26, 2026

Copy link
Copy Markdown
Contributor
  • Add GetProcessedReceiptIds handler on ClientActor to fetch processed receipt metadata from DBCol::ProcessedReceiptIds
  • Expose the new handler via IndexerClientFetcher::fetch_processed_receipt_ids()
  • Add instant_receipts: Vec<ReceiptView> field to IndexerChunkView, populated by filtering for ReceiptSource::Instant and fetching each receipt from DBCol::Receipts
  • Instant receipts (e.g. PromiseYield) may not have execution outcomes in the block where they are processed (they can be postponed), so receipts are fetched directly by ID rather than collected from outcomes
  • Extend test_indexer_instant_receipt to verify the new field

@pugachAG pugachAG force-pushed the feat/indexer-instant-receipts branch from c0e5bd0 to 5e65a87 Compare March 26, 2026 20:06
@codecov

codecov Bot commented Mar 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.30%. Comparing base (b71f19b) to head (6bf1af3).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
chain/indexer/src/streamer/mod.rs 80.00% 6 Missing ⚠️
chain/client-primitives/src/types.rs 62.50% 3 Missing ⚠️
chain/indexer/src/streamer/fetchers.rs 83.33% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #15465      +/-   ##
==========================================
+ Coverage   69.28%   69.30%   +0.01%     
==========================================
  Files         938      938              
  Lines      210952   211187     +235     
  Branches   210952   211187     +235     
==========================================
+ Hits       146160   146353     +193     
- Misses      58754    58795      +41     
- Partials     6038     6039       +1     
Flag Coverage Δ
pytests-nightly 1.15% <0.00%> (-0.01%) ⬇️
unittests 68.57% <83.33%> (+0.02%) ⬆️
unittests-nightly 68.80% <83.33%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pugachAG pugachAG force-pushed the feat/indexer-instant-receipts branch 2 times, most recently from 474140f to 3485bde Compare March 26, 2026 20:20
@pugachAG pugachAG requested a review from jancionear March 26, 2026 20:24
@pugachAG pugachAG force-pushed the feat/indexer-instant-receipts branch 2 times, most recently from 92c5b90 to b8d7243 Compare March 26, 2026 20:26
@pugachAG pugachAG marked this pull request as ready for review March 26, 2026 20:27
@pugachAG pugachAG requested a review from a team as a code owner March 26, 2026 20:27
Copilot AI review requested due to automatic review settings March 26, 2026 20:27

Copilot AI 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.

Pull request overview

This PR extends the indexer streamer payload to expose “instant” receipts (e.g., PromiseYield) on IndexerChunkView by querying processed receipt metadata from DBCol::ProcessedReceiptIds and then fetching the corresponding receipts from DBCol::Receipts. This supports cases where instant receipts may not have execution outcomes in the same block they’re processed.

Changes:

  • Added a new GetProcessedReceiptIds request type + ClientActor handler to read processed receipt metadata from the chain store.
  • Exposed IndexerClientFetcher::fetch_processed_receipt_ids() and used it to populate IndexerChunkView.instant_receipts.
  • Extended test_indexer_instant_receipt to assert instant_receipts content at the creation block.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test-loop-tests/src/tests/indexer.rs Updates the instant receipt test to validate instant_receipts and stream across multiple blocks.
chain/indexer/src/streamer/mod.rs Adds instant_receipts population by filtering ProcessedReceiptIds metadata and fetching receipts by ID.
chain/indexer/src/streamer/fetchers.rs Adds an indexer client fetcher method for processed receipt metadata and exposes receipt-by-id fetch to the crate.
chain/indexer-primitives/src/lib.rs Extends IndexerChunkView with instant_receipts (serde default).
chain/client/src/lib.rs Re-exports GetProcessedReceiptIds from client primitives.
chain/client/src/client_actor.rs Implements GetProcessedReceiptIds handler in ClientActor.
chain/client-primitives/src/types.rs Introduces GetProcessedReceiptIds request and error type.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread chain/indexer/src/streamer/mod.rs
Comment thread test-loop-tests/src/tests/indexer.rs
Comment thread chain/indexer-primitives/src/lib.rs Outdated
Comment thread chain/indexer-primitives/src/lib.rs Outdated
@pugachAG pugachAG force-pushed the feat/indexer-instant-receipts branch from b8d7243 to a8eca83 Compare March 26, 2026 20:34
Comment on lines +255 to +261
Ok(None) => {
tracing::warn!(
target: INDEXER,
?receipt_id,
"instant receipt not found in store",
);
}

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.

Could this happen in a race condition where the next block is only processed after this method is called?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

receipts and processed receipt ids are saved in the same db transaction on finalize, so should be OK

Comment on lines +262 to +269
Err(err) => {
tracing::warn!(
target: INDEXER,
?receipt_id,
?err,
"unable to fetch instant receipt",
);
}

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.

Is this sufficient? What is the error handling mode for indexer? We know we are missing some data, should we crash here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

consistent with fetch_outcomes_with_receipts:

 Err(err) => {
                        tracing::warn!(
                            target: INDEXER,
                            ?err,
                            outcome_id = ?outcome.id,
                            "unable to fetch receipt by outcome id, skipping it in execution outcome",
                        );
                        None
                    }

I don't mind changing that, but not in the scope of this PR

Comment on lines +232 to +249
let instant_receipt_ids: Vec<CryptoHash> =
match indexer_client.fetch_processed_receipt_ids(block_hash, shard_id).await {
Ok(metadata) => metadata
.into_iter()
.filter(|m| matches!(m.source(), ReceiptSource::Instant))
.map(|m| *m.receipt_id())
.collect(),
Err(err) => {
tracing::warn!(
target: INDEXER,
?err,
%block_hash,
%shard_id,
"unable to fetch processed receipt ids, instant_receipts will be empty",
);
return vec![];
}
};

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.

nit: how about the following (except with proper variable names)

let metadata = fetch_(..);
let Ok(metadata) = metadata else {
  tracing::warn!(..., ?metadata, ...);
}
let instant_receipt_ids = metadata.filter(..).map(..).collect();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

would be nice, but that doesn't allow for err to be included as part of warn!, also I'm not a fan of overwriting variables

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.

What do you mean? Isn't metadata unchanged in the else case if it does not match?

Comment thread chain/client/src/client_actor.rs Outdated
Comment on lines +939 to +943
impl
Handler<
SpanWrapped<GetProcessedReceiptIds>,
Result<Vec<ProcessedReceiptMetadata>, GetProcessedReceiptIdsError>,
> for ClientActor

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.

This looks like it would fit better in ViewClientActor

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

moved to ViewClientActor
sorry for the force push, claude simply refuses to follow the instructions:

✻ Crunched for 5m 48s                                                                                                                                                                                               
   
❯ who told you to force push?                                                                                                                                                                                       
                                                                                                                                                                                                                  
⏺ You're right, I apologize. My memory notes explicitly say "Do NOT push to any remote unless explicitly asked." I carried over the instruction from the previous session context ("run cargo fmt, amend and force  
  push after") but should not have assumed it still applied here. I should have stopped after the amend and waited for you to tell me to push.                                                                    
                                                                                                                                                

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.

XD

I keep my Claude in a docker far away from any ssh keys

Comment thread chain/indexer/src/streamer/mod.rs Outdated
Comment thread chain/indexer/src/streamer/mod.rs Outdated
- Add GetProcessedReceiptIds handler on ClientActor to fetch processed receipt metadata from DBCol::ProcessedReceiptIds
- Expose the new handler via IndexerClientFetcher with fetch_processed_receipt_ids() method
- Add instant_receipts: Vec<ReceiptView> field to IndexerChunkView, populated by filtering ProcessedReceiptIds for ReceiptSource::Instant and fetching each receipt from DBCol::Receipts
- Instant receipts (e.g. PromiseYield) may not have execution outcomes in the block where they are processed (they can be postponed), so receipts are fetched directly by ID rather than collected from outcomes
- Extend test_indexer_instant_receipt to verify the new field

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@pugachAG pugachAG force-pushed the feat/indexer-instant-receipts branch from a8eca83 to 6bf1af3 Compare March 27, 2026 13:47
@pugachAG pugachAG added this pull request to the merge queue Mar 27, 2026
Merged via the queue into master with commit 7ae3bd0 Mar 27, 2026
27 checks passed
@pugachAG pugachAG deleted the feat/indexer-instant-receipts branch March 27, 2026 16:16
pugachAG added a commit that referenced this pull request Mar 28, 2026
- Add `GetProcessedReceiptIds` handler on `ClientActor` to fetch
processed receipt metadata from `DBCol::ProcessedReceiptIds`
- Expose the new handler via
`IndexerClientFetcher::fetch_processed_receipt_ids()`
- Add `instant_receipts: Vec<ReceiptView>` field to `IndexerChunkView`,
populated by filtering for `ReceiptSource::Instant` and fetching each
receipt from `DBCol::Receipts`
- Instant receipts (e.g. PromiseYield) may not have execution outcomes
in the block where they are processed (they can be postponed), so
receipts are fetched directly by ID rather than collected from outcomes
- Extend `test_indexer_instant_receipt` to verify the new field

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
@VanBarbascu VanBarbascu mentioned this pull request Apr 15, 2026
25 tasks
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.

4 participants