Skip to content

Conversation

@zhangchiqing
Copy link
Member

@zhangchiqing zhangchiqing commented Nov 14, 2025

Close #8121

This PR addresses two issues:

  • Problem 1: Slow startup when Access Node is far behind
    When an Access Node is far behind, startup is slow because it attempts to download collections for all finalized heights with missing collections, causing extended downtime.
    Solution: Switched to a job queue that focuses on the next missing height to fetch. This enables faster startup, reduces downtime, and speeds up catch-up.
  • Problem 2: Lock contention from dual collection syncing
    Collections can be synced from either collection nodes or execution nodes. Currently, the Access Node syncs from both. Because the storage function uses a lock, concurrent syncing causes both procedures to block each other.
    Solution: Prioritize syncing from execution nodes via execution data syncing, and allow only one sync procedure at a time. Syncing from collection nodes is only enabled when execution data syncing is turned off. This reduces lock contention, speeds up indexing, and reduces load on collection nodes.

Collection Indexing Refactoring POC

  1. Finalization block processor: Moved from ingestion2 to the finalized_indexer engine. It indexes guarantees to determine finalized transactions.
  2. Receipts ingestion: Extracted from the ingestion engine into a dedicated ingest_receipt engine. In factor, we don't need this engine, because the follower engine is already storing each receipts for verified blocks.
  3. Execution data indexing: Removed collection indexing. It now only indexes registers and events.
  4. Collection indexing architecture: Collection indexing is handled by two engines in engine/access/collection_sync, with only one enabled at startup. This structure supports a future hybrid mode.
  5. Execution data-based collection indexing (when execution data indexing is enabled): The engine/access/collection_sync/execution_data_index/processor.go engine indexes collections from execution data. It receives notifications when new execution data is downloaded and indexes the collections from that data.
  6. Collection node-based collection fetching (when execution data indexing is disabled): The engine/access/collection_sync/fetcher/engine.go engine fetches collections from collection nodes and indexes them.

// `e.consumers`.
// Note: the `e.consumers` will be guaranteed to receive at least one `OnExecutionDataFetched` event
// for each sealed block in consecutive block height order.
e.notificationConsumer, err = jobqueue.NewComponentConsumer(
Copy link
Member Author

Choose a reason for hiding this comment

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

I simplified the requester by removing the notification consumer entirely. Instead, we are just calling e.distributor.OnExecutionDataReceived().

Note, the OnExecutionDataReceived used to be called with the execution data read from storage, but actually, no consumer actually make use the execution data, because the consumer will read execution data with their next unprocessed index to ensure data for all heights are processed.

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.

[Access] Asynchronous Collection Indexing Design

4 participants