Dispatch snap server request processing off Netty event loop#10083
Merged
macfarla merged 14 commits intobesu-eth:mainfrom Mar 25, 2026
Merged
Dispatch snap server request processing off Netty event loop#10083macfarla merged 14 commits intobesu-eth:mainfrom
macfarla merged 14 commits intobesu-eth:mainfrom
Conversation
SnapProtocolManager.processMessage() was calling snapMessages.dispatch() synchronously on the Netty event loop thread for incoming GET_* snap requests. These handlers do heavy work (trie traversal, proof generation, DB reads) that can take several seconds, blocking the event loop and preventing the server from responding to concurrent ETH protocol messages such as GET_BLOCK_HEADERS. This caused the client to accumulate 5+ (eth,3) timeouts and disconnect the server with TIMEOUT. Fix: for even-coded snap request messages (GET_ACCOUNT_RANGE, GET_STORAGE_RANGE, GET_BYTECODES, GET_TRIE_NODES), dispatch the heavy snapMessages.dispatch() work and the subsequent send() to EthScheduler's service thread pool. The Netty event loop now returns immediately after dispatching, staying free to handle ETH messages. Response messages (odd codes) are already handled by dispatchMessage() and need no changes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Dispatches inbound SNAP GET_* request handling off the Netty event loop to avoid blocking ETH protocol processing and timeouts.
Changes:
- Add
EthSchedulertoSnapProtocolManagerand wire it fromBesuControllerBuilder. - Offload even-coded SNAP request processing (
GET_*) toEthSchedulerservice threads, including response sending. - Adjust malformed SNAP message handling to ignore malformed request payloads instead of disconnecting.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapProtocolManager.java | Offloads SNAP GET_* request dispatch + response send to service thread pool via EthScheduler. |
| app/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java | Wires EthScheduler into SnapProtocolManager construction. |
...um/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapProtocolManager.java
Outdated
Show resolved
Hide resolved
...um/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapProtocolManager.java
Outdated
Show resolved
Hide resolved
...um/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapProtocolManager.java
Outdated
Show resolved
Hide resolved
This was referenced Mar 23, 2026
jframe
reviewed
Mar 24, 2026
...um/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapProtocolManager.java
Outdated
Show resolved
Hide resolved
...um/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapProtocolManager.java
Outdated
Show resolved
Hide resolved
...um/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapProtocolManager.java
Outdated
Show resolved
Hide resolved
...um/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapProtocolManager.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
jframe
approved these changes
Mar 24, 2026
ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/snap/SnapV1.java
Outdated
Show resolved
Hide resolved
Keep both EthScheduler (dispatch-off-netty) and ProtocolSchedule (SNAP2 capability detection) parameters in SnapProtocolManager constructor. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Contributor
Code reviewFound 2 issues:
🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
- Add REQUEST_CODES to SnapV2 so GET_BLOCK_ACCESS_LISTS (0x08) requests from snap/2 peers are scheduled off the Netty event loop rather than silently dropped - Attach .exceptionally() handler to the CompletableFuture returned by scheduleServiceTask to log unexpected non-cancellation failures that would otherwise be swallowed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
pinges
reviewed
Mar 25, 2026
Contributor
pinges
left a comment
There was a problem hiding this comment.
Please catch FramingException as well. See comment.
...um/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapProtocolManager.java
Show resolved
Hide resolved
unwrapMessageData() can throw FramingException (decompression failure) as well as RLPException. Catch both and disconnect the peer, consistent with the pre-schedule FramingException handling in processMessage. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
…to dispatch-off-netty-only
ahamlat
pushed a commit
to daniellehrner/besu
that referenced
this pull request
Mar 25, 2026
…h#10083) * Dispatch snap server request processing off the Netty event loop SnapProtocolManager.processMessage() was calling snapMessages.dispatch() synchronously on the Netty event loop thread for incoming GET_* snap requests. These handlers do heavy work (trie traversal, proof generation, DB reads) that can take several seconds, blocking the event loop and preventing the server from responding to concurrent ETH protocol messages such as GET_BLOCK_HEADERS. This caused the client to accumulate 5+ (eth,3) timeouts and disconnect the server with TIMEOUT. Fix: for even-coded snap request messages, dispatch the heavy snapMessages.dispatch() work and the subsequent send() to EthScheduler's service thread pool. The Netty event loop now returns immediately after dispatching, staying free to handle ETH messages. Response messages (odd codes) are already handled by dispatchMessage() and need no changes. - Add REQUEST_CODES to SnapV2 so GET_BLOCK_ACCESS_LISTS (0x08) requests from snap/2 peers are scheduled off the Netty event loop Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> * Catch FramingException inside scheduled snap request task --------- Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SnapProtocolManager.processMessage() was calling snapMessages.dispatch() synchronously on the Netty event loop thread for incoming GET_* snap requests. These handlers do heavy work (trie traversal, proof generation, DB reads) that can take several seconds, blocking the event loop and preventing the server from responding to concurrent ETH protocol messages such as GET_BLOCK_HEADERS.
When testing with besu server <> besu client, this caused the client to accumulate 5+ (eth,3) timeouts and disconnect the server with TIMEOUT.
Fix: for even-coded snap request messages (GET_ACCOUNT_RANGE, GET_STORAGE_RANGE, GET_BYTECODES, GET_TRIE_NODES), dispatch the heavy snapMessages.dispatch() work and the subsequent send() to EthScheduler's service thread pool. The Netty event loop now returns immediately after dispatching, staying free to handle ETH messages. Response messages (odd codes) are already handled by dispatchMessage() and need no changes.
Thanks for sending a pull request! Have you done the following?
doc-change-requiredlabel to this PR if updates are required.Locally, you can run these tests to catch failures early:
./gradlew spotlessApply./gradlew build./gradlew acceptanceTest./gradlew integrationTest./gradlew ethereum:referenceTests:referenceTests