Skip to content

Conversation

wunameya
Copy link
Contributor

@wunameya wunameya commented Sep 27, 2025

Supports Provider-side asynchronous
支持服务端异步调用

Summary by CodeRabbit

  • New Features

    • Added server-side asynchronous RPC support over the Bolt protocol, including context switch/restore for async handling, single-send protection, server events on reply, and the ability to return results or errors asynchronously.
  • Documentation

    • Added a runnable example (service, client, and interface) demonstrating asynchronous RPC usage with a simple hello operation.

@sofastack-cla sofastack-cla bot added cla:yes CLA is ok size/L labels Sep 27, 2025
Copy link
Contributor

coderabbitai bot commented Sep 27, 2025

Walkthrough

Introduces an example async RPC service (interface, impl, client, server) under tests. Adds BoltAsyncContext to manage server-side async responses, handling context switch/reset and single-send enforcement. Updates BoltServerProcessor to attach the incoming request into RpcInternalContext for async handling.

Changes

Cohort / File(s) Summary of changes
Example async service and runner
example/src/test/java/com/alipay/sofa/rpc/serviceasync/HelloService.java, example/src/test/java/com/alipay/sofa/rpc/serviceasync/HelloServiceImpl.java, example/src/test/java/com/alipay/sofa/rpc/serviceasync/start/Client.java, example/src/test/java/com/alipay/sofa/rpc/serviceasync/start/Service.java
Adds a simple HelloService interface and async implementation using a new thread and BoltAsyncContext; adds a server bootstrap exporting the service and a client loop invoking sayHello over bolt.
Bolt remoting async support
remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/message/bolt/BoltAsyncContext.java, remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/server/bolt/BoltServerProcessor.java
Introduces BoltAsyncContext for server-side async response handling (context capture/switch/reset, write/writeException). Modifies processor to stash incoming SofaRequest in RpcInternalContext for async workflows.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant B as Bolt Transport
  participant S as Service (HelloServiceImpl)
  participant T as Worker Thread
  participant AC as BoltAsyncContext

  C->>B: sayHello("world")
  B->>S: invoke(request)
  Note over S: Processor attaches request to RpcInternalContext
  S->>S: create BoltAsyncContext
  S->>T: spawn async task
  S-->>B: return (no immediate response)

  rect rgba(220, 235, 255, 0.5)
  note over T,AC: Async phase (server-side)
  T->>AC: signalContextSwitch()
  T->>AC: write("Hello world") or writeException(e)
  AC-->>B: sendResponse(SofaResponse)
  AC->>AC: resetContext()
  end

  B-->>C: SofaResponse (result or exception)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I thump my paws, the threads take flight,
A bolt of greet in server night—
Context hops, then snaps back tight,
One send only, just done right.
Hello, world! I sip some tea,
Async dreams in RPC. 🐇⚡

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly summarizes the primary change of enabling provider-side asynchronous behavior and directly reflects the main objective of the pull request without extraneous detail.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58a01c7 and 77ec4d4.

📒 Files selected for processing (2)
  • remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/message/bolt/BoltAsyncContext.java (1 hunks)
  • remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/server/bolt/BoltServerProcessor.java (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/server/bolt/BoltServerProcessor.java (1)
core/api/src/main/java/com/alipay/sofa/rpc/common/RpcConstants.java (1)
  • RpcConstants (28-747)
remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/message/bolt/BoltAsyncContext.java (8)
core/api/src/main/java/com/alipay/sofa/rpc/common/RemotingConstants.java (1)
  • RemotingConstants (27-264)
core/api/src/main/java/com/alipay/sofa/rpc/common/RpcConstants.java (1)
  • RpcConstants (28-747)
core/api/src/main/java/com/alipay/sofa/rpc/context/RpcInternalContext.java (1)
  • RpcInternalContext (40-503)
core/api/src/main/java/com/alipay/sofa/rpc/context/RpcInvokeContext.java (1)
  • RpcInvokeContext (32-477)
core/api/src/main/java/com/alipay/sofa/rpc/core/request/SofaRequest.java (1)
  • SofaRequest (34-315)
core/api/src/main/java/com/alipay/sofa/rpc/core/response/SofaResponse.java (1)
  • SofaResponse (30-218)
core/api/src/main/java/com/alipay/sofa/rpc/event/EventBus.java (1)
  • EventBus (38-160)
core/api/src/main/java/com/alipay/sofa/rpc/event/ServerSendEvent.java (1)
  • ServerSendEvent (30-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: sca

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf3a261 and 58a01c7.

📒 Files selected for processing (7)
  • core/api/src/main/java/com/alipay/sofa/rpc/common/RemotingConstants.java (1 hunks)
  • example/src/test/java/com/alipay/sofa/rpc/serviceasync/HelloService.java (1 hunks)
  • example/src/test/java/com/alipay/sofa/rpc/serviceasync/HelloServiceImpl.java (1 hunks)
  • example/src/test/java/com/alipay/sofa/rpc/serviceasync/start/Client.java (1 hunks)
  • example/src/test/java/com/alipay/sofa/rpc/serviceasync/start/Service.java (1 hunks)
  • remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/message/bolt/BoltAsyncContext.java (1 hunks)
  • remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/server/bolt/BoltServerProcessor.java (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-08T06:59:23.963Z
Learnt from: EvenLjj
PR: sofastack/sofa-rpc#1488
File: remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/interceptor/ServerReqHeaderInterceptor.java:105-120
Timestamp: 2025-05-08T06:59:23.963Z
Learning: In SOFA RPC, TripleTracerAdapter.serverReceived() sets the invocation type on the SofaRequest based on the gRPC method type (CLIENT_STREAMING, SERVER_STREAMING, BIDI_STREAMING), but the SofaRequest.isAsync() method does not directly recognize these streaming types as asynchronous. According to EvenLjj, some modification in TripleTracerAdapter.serverReceived makes sofaRequest.isAsync() return true for streaming requests.

Applied to files:

  • remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/server/bolt/BoltServerProcessor.java
🧬 Code graph analysis (4)
example/src/test/java/com/alipay/sofa/rpc/serviceasync/HelloServiceImpl.java (1)
remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/message/bolt/BoltAsyncContext.java (1)
  • BoltAsyncContext (31-116)
remoting/remoting-bolt/src/main/java/com/alipay/sofa/rpc/server/bolt/BoltServerProcessor.java (3)
core/api/src/main/java/com/alipay/sofa/rpc/common/RpcConstants.java (1)
  • RpcConstants (28-747)
core/common/src/main/java/com/alipay/sofa/rpc/common/utils/CommonUtils.java (1)
  • CommonUtils (30-278)
core/api/src/main/java/com/alipay/sofa/rpc/common/RemotingConstants.java (1)
  • RemotingConstants (27-269)
example/src/test/java/com/alipay/sofa/rpc/serviceasync/start/Client.java (2)
core/api/src/main/java/com/alipay/sofa/rpc/config/ConsumerConfig.java (1)
  • ConsumerConfig (71-1044)
core/api/src/main/java/com/alipay/sofa/rpc/log/LoggerFactory.java (1)
  • LoggerFactory (29-70)
example/src/test/java/com/alipay/sofa/rpc/serviceasync/start/Service.java (3)
core/api/src/main/java/com/alipay/sofa/rpc/config/ProviderConfig.java (1)
  • ProviderConfig (55-561)
core/api/src/main/java/com/alipay/sofa/rpc/config/ServerConfig.java (1)
  • ServerConfig (66-909)
example/src/test/java/com/alipay/sofa/rpc/serviceasync/HelloServiceImpl.java (1)
  • HelloServiceImpl (21-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: sca

@OrezzerO
Copy link
Contributor

Each time we use isServerAsync, it is aside with isAsyncChain. Does it indicate that isAsyncChain and isServerAsync are the same thing ?

@wunameya
Copy link
Contributor Author

Each time we use isServerAsync, it is aside with isAsyncChain. Does it indicate that isAsyncChain and isServerAsync are the same thing ?

The purpose of using isAsyncChain here is for the Async Response Callback, which enables sending data to the upstream when data is received from the downstream.
屏幕截图 2025-09-28 214939
And it is set here.
屏幕截图 2025-09-28 215622

The purpose of isServerAsync is to implement server-side asynchrony, and it is set here.
屏幕截图 2025-09-28 215244

@OrezzerO
Copy link
Contributor

What I mean is, if you use isAsyncChain in BoltAsyncContext, you'll achieve the same effect. So creating another isServerAsync seems redundant.

n the thread model, these two also seem to have the same meaning: ignoring the return value of the current thread invoker.

@wunameya
Copy link
Contributor Author

wunameya commented Oct 2, 2025

What I mean is, if you use isAsyncChain in BoltAsyncContext, you'll achieve the same effect. So creating another isServerAsync seems redundant.

n the thread model, these two also seem to have the same meaning: ignoring the return value of the current thread invoker.

I think you are right, and I did it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants