This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 680d50f3e docs: refine gRPC support guides (#3767)
680d50f3e is described below

commit 680d50f3eaad8524b04795fdd81abfdaaeebde36
Author: Shawn Yang <[email protected]>
AuthorDate: Tue Jun 16 21:26:49 2026 +0530

    docs: refine gRPC support guides (#3767)
    
    ## Why?
    
    
    
    ## What does this PR do?
    
    
    
    ## Related issues
    
    
    
    ## AI Contribution Checklist
    
    
    
    - [ ] Substantial AI assistance was used in this PR: `yes` / `no`
    - [ ] If `yes`, I included a completed [AI Contribution
    
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
    in this PR description and the required `AI Usage Disclosure`.
    - [ ] If `yes`, my PR description includes the required `ai_review`
    summary and screenshot evidence of the final clean AI review results
    from both fresh reviewers on the current PR diff or current HEAD after
    the latest code changes.
    
    
    
    ## Does this PR introduce any user-facing change?
    
    
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
---
 docs/guide/java/grpc-support.md       | 170 ++++++++++++++++++++++++++++++++--
 docs/guide/javascript/grpc-support.md |  29 ++++++
 docs/guide/kotlin/grpc-support.md     | 127 ++++++++++++++++++++++---
 docs/guide/python/grpc-support.md     |  81 +++++++++++++---
 docs/guide/rust/grpc-support.md       | 115 ++++++++++++++++++++++-
 5 files changed, 486 insertions(+), 36 deletions(-)

diff --git a/docs/guide/java/grpc-support.md b/docs/guide/java/grpc-support.md
index 7bebb010f..d1c899329 100644
--- a/docs/guide/java/grpc-support.md
+++ b/docs/guide/java/grpc-support.md
@@ -201,12 +201,170 @@ service Greeter {
 
 Generated Java service methods follow grpc-java conventions:
 
-- Unary and server-streaming methods receive a request object and a
-  `StreamObserver` for responses.
-- Client-streaming and bidirectional methods return a `StreamObserver` for
-  incoming requests and receive a `StreamObserver` for outgoing responses.
-- Blocking stubs expose the grpc-java blocking APIs for supported streaming
-  shapes.
+| IDL shape                                 | Server method shape              
                      | Client method shape                    |
+| ----------------------------------------- | 
------------------------------------------------------ | 
-------------------------------------- |
+| `rpc A (Req) returns (Res)`               | `void a(Req request, 
StreamObserver<Res> responses)`   | blocking, async, and future unary stub |
+| `rpc A (Req) returns (stream Res)`        | `void a(Req request, 
StreamObserver<Res> responses)`   | blocking iterator or async observer    |
+| `rpc A (stream Req) returns (Res)`        | `StreamObserver<Req> 
a(StreamObserver<Res> responses)` | async request observer                 |
+| `rpc A (stream Req) returns (stream Res)` | `StreamObserver<Req> 
a(StreamObserver<Res> responses)` | async request observer                 |
+
+Server implementations can use the generated streaming method shapes directly:
+
+```java
+package demo.greeter;
+
+import io.grpc.stub.StreamObserver;
+import java.util.ArrayList;
+import java.util.List;
+
+final class GreeterService extends GreeterGrpc.GreeterImplBase {
+  @Override
+  public void lotsOfReplies(
+      HelloRequest request, StreamObserver<HelloReply> responseObserver) {
+    HelloReply first = new HelloReply();
+    first.setReply("Hello, " + request.getName());
+    responseObserver.onNext(first);
+
+    HelloReply second = new HelloReply();
+    second.setReply("Welcome, " + request.getName());
+    responseObserver.onNext(second);
+    responseObserver.onCompleted();
+  }
+
+  @Override
+  public StreamObserver<HelloRequest> lotsOfGreetings(
+      StreamObserver<HelloReply> responseObserver) {
+    List<String> names = new ArrayList<>();
+    return new StreamObserver<>() {
+      @Override
+      public void onNext(HelloRequest request) {
+        names.add(request.getName());
+      }
+
+      @Override
+      public void onError(Throwable error) {
+        responseObserver.onError(error);
+      }
+
+      @Override
+      public void onCompleted() {
+        HelloReply reply = new HelloReply();
+        reply.setReply(String.join(", ", names));
+        responseObserver.onNext(reply);
+        responseObserver.onCompleted();
+      }
+    };
+  }
+
+  @Override
+  public StreamObserver<HelloRequest> chat(
+      StreamObserver<HelloReply> responseObserver) {
+    return new StreamObserver<>() {
+      @Override
+      public void onNext(HelloRequest request) {
+        HelloReply reply = new HelloReply();
+        reply.setReply("Hello, " + request.getName());
+        responseObserver.onNext(reply);
+      }
+
+      @Override
+      public void onError(Throwable error) {
+        responseObserver.onError(error);
+      }
+
+      @Override
+      public void onCompleted() {
+        responseObserver.onCompleted();
+      }
+    };
+  }
+}
+```
+
+Generated clients return the standard grpc-java call shapes:
+
+```java
+package demo.greeter;
+
+import io.grpc.stub.StreamObserver;
+import java.util.Iterator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+final class StreamingClient {
+  private final GreeterGrpc.GreeterBlockingStub blockingStub;
+  private final GreeterGrpc.GreeterStub asyncStub;
+
+  StreamingClient(
+      GreeterGrpc.GreeterBlockingStub blockingStub,
+      GreeterGrpc.GreeterStub asyncStub) {
+    this.blockingStub = blockingStub;
+    this.asyncStub = asyncStub;
+  }
+
+  void run() throws InterruptedException {
+    Iterator<HelloReply> replies =
+        blockingStub.lotsOfReplies(newRequest("Fory"));
+    while (replies.hasNext()) {
+      System.out.println(replies.next().getReply());
+    }
+
+    CountDownLatch greetingsDone = new CountDownLatch(1);
+    StreamObserver<HelloRequest> greetings =
+        asyncStub.lotsOfGreetings(new StreamObserver<>() {
+          @Override
+          public void onNext(HelloReply reply) {
+            System.out.println(reply.getReply());
+          }
+
+          @Override
+          public void onError(Throwable error) {
+            greetingsDone.countDown();
+          }
+
+          @Override
+          public void onCompleted() {
+            greetingsDone.countDown();
+          }
+        });
+    greetings.onNext(newRequest("Ada"));
+    greetings.onNext(newRequest("Grace"));
+    greetings.onCompleted();
+    greetingsDone.await(5, TimeUnit.SECONDS);
+
+    CountDownLatch chatDone = new CountDownLatch(1);
+    StreamObserver<HelloRequest> chat =
+        asyncStub.chat(new StreamObserver<>() {
+          @Override
+          public void onNext(HelloReply reply) {
+            System.out.println(reply.getReply());
+          }
+
+          @Override
+          public void onError(Throwable error) {
+            chatDone.countDown();
+          }
+
+          @Override
+          public void onCompleted() {
+            chatDone.countDown();
+          }
+        });
+    chat.onNext(newRequest("Fory"));
+    chat.onCompleted();
+    chatDone.await(5, TimeUnit.SECONDS);
+  }
+
+  private static HelloRequest newRequest(String name) {
+    HelloRequest request = new HelloRequest();
+    request.setName(name);
+    return request;
+  }
+}
+```
+
+The generated descriptors preserve the exact IDL service and method names for
+the gRPC path.
 
 ## Operations
 
diff --git a/docs/guide/javascript/grpc-support.md 
b/docs/guide/javascript/grpc-support.md
index 32ca80517..696ecef24 100644
--- a/docs/guide/javascript/grpc-support.md
+++ b/docs/guide/javascript/grpc-support.md
@@ -23,6 +23,12 @@ Fory can generate JavaScript service companions for schemas 
that define
 services. The generated service code uses normal gRPC transports while request
 and response objects are serialized with Fory instead of protobuf.
 
+Use this mode when both RPC peers are generated from the same Fory IDL,
+protobuf IDL, or FlatBuffers IDL and both sides expect Fory-encoded message
+bodies. Use normal protobuf gRPC generation for APIs that must be consumed by
+generic protobuf clients, reflection tools, or components that expect protobuf
+message bytes.
+
 Use `--grpc` for Node.js server and client code. Use `--grpc-web` for browser
 clients that call a gRPC-Web compatible server or proxy.
 
@@ -47,6 +53,9 @@ package used by your application.
 
 ## Define a Service
 
+Service definitions can come from Fory IDL, protobuf IDL, or FlatBuffers
+`rpc_service` definitions. A Fory IDL service looks like this:
+
 ```protobuf
 package demo.greeter;
 
@@ -292,3 +301,23 @@ gRPC operational features still belong to the transport 
package:
 - Deadlines and cancellation
 - Client and server interceptors
 - Load balancing and deployment-specific proxy configuration
+
+## Troubleshooting
+
+### Missing gRPC Packages
+
+Add `@grpc/grpc-js` for Node.js companions or `grpc-web` for browser
+companions. `@apache-fory/core` intentionally does not depend on either
+transport package.
+
+### gRPC-Web Client-Streaming or Bidirectional RPCs Are Rejected
+
+gRPC-Web does not support client-streaming or bidirectional streaming. Generate
+Node.js companions with `--grpc` for those shapes, or expose unary and
+server-streaming methods to browser clients.
+
+### Protobuf Clients Cannot Decode the Service
+
+Fory gRPC companions do not use protobuf wire encoding for messages. Use a
+Fory-generated client for Fory-generated services, or provide a separate
+protobuf service endpoint for generic protobuf clients.
diff --git a/docs/guide/kotlin/grpc-support.md 
b/docs/guide/kotlin/grpc-support.md
index ae12f9e0f..cf517df44 100644
--- a/docs/guide/kotlin/grpc-support.md
+++ b/docs/guide/kotlin/grpc-support.md
@@ -23,7 +23,13 @@ Fory IDL can generate Kotlin coroutine gRPC companions. The 
generated gRPC
 files use normal grpc-java and grpc-kotlin APIs, while each request and 
response
 message is serialized with Fory.
 
-## Dependencies
+Use this mode when both RPC peers are generated from the same Fory IDL,
+protobuf IDL, or FlatBuffers IDL and both sides expect Fory-encoded message
+bodies. Use normal protobuf gRPC generation for APIs that must be consumed by
+generic protobuf clients, reflection tools, or components that expect protobuf
+message bytes.
+
+## Add Dependencies
 
 Add Fory Kotlin, KSP, grpc-java, grpc-kotlin, coroutines, and one grpc-java
 transport to the application or service module that compiles the generated
@@ -51,9 +57,10 @@ Use a different grpc-java transport if your application 
already standardizes on
 one. Generated Kotlin Fory gRPC does not require `grpc-protobuf` for payload
 encoding.
 
-## Generate Code
+## Define a Service
 
-For a schema such as:
+Service definitions can come from Fory IDL, protobuf IDL, or FlatBuffers
+`rpc_service` definitions. A Fory IDL service looks like this:
 
 ```protobuf
 package demo.greeter;
@@ -71,18 +78,27 @@ service Greeter {
 }
 ```
 
-run:
+Generate Kotlin model and gRPC companion code with `--grpc`:
 
 ```bash
 foryc service.fdl --kotlin_out=./generated/kotlin --grpc
 ```
 
-The compiler writes Kotlin model files, a schema module such as
-`ServiceForyModule.kt`, and one service companion such as `GreeterGrpcKt.kt`.
+For this schema, the Kotlin generator emits:
+
+| File                | Purpose                                      |
+| ------------------- | -------------------------------------------- |
+| `HelloRequest.kt`   | Fory model type for the request              |
+| `HelloReply.kt`     | Fory model type for the response             |
+| `ServiceForyModule` | Fory registration module for generated types |
+| `GreeterGrpcKt.kt`  | Coroutine service base, stubs, and codecs    |
+
 Run KSP when compiling the generated model files so the schema serializers are
-available at runtime.
+available at runtime. Generated request and response types are registered by
+the generated schema module used by the service companion, so service
+implementations do not perform manual serializer registration.
 
-## Server
+## Implement a Server
 
 Implement the generated coroutine base class and register it with a normal
 grpc-java server.
@@ -108,7 +124,7 @@ val server = ServerBuilder
 Unimplemented generated methods fail with gRPC `UNIMPLEMENTED`. Exceptions
 thrown by your service method follow grpc-kotlin server behavior.
 
-## Client
+## Create a Client
 
 Construct the generated coroutine stub directly from a grpc-java channel.
 
@@ -130,7 +146,18 @@ Channel construction, shutdown, deadlines, credentials, 
interceptors, load
 balancing, retries, and server lifecycle stay normal grpc-java/grpc-kotlin
 responsibilities.
 
-## Streaming
+## Streaming RPCs
+
+Fory service definitions can use the same gRPC streaming shapes:
+
+```protobuf
+service Greeter {
+  rpc SayHello (HelloRequest) returns (HelloReply);
+  rpc LotsOfReplies (HelloRequest) returns (stream HelloReply);
+  rpc LotsOfGreetings (stream HelloRequest) returns (HelloReply);
+  rpc Chat (stream HelloRequest) returns (stream HelloReply);
+}
+```
 
 Streaming RPCs use `kotlinx.coroutines.flow.Flow`.
 
@@ -144,6 +171,78 @@ Streaming RPCs use `kotlinx.coroutines.flow.Flow`.
 The generated method path keeps the exact service and method names from the
 schema, for example `/demo.greeter.Greeter/SayHello`.
 
+Server implementations can return or consume `Flow` values directly:
+
+```kotlin
+import demo.greeter.GreeterGrpcKt
+import demo.greeter.HelloReply
+import demo.greeter.HelloRequest
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.toList
+
+class GreeterService : GreeterGrpcKt.GreeterCoroutineImplBase() {
+  override fun lotsOfReplies(request: HelloRequest): Flow<HelloReply> = flow {
+    emit(HelloReply(reply = "Hello, ${request.name}"))
+    emit(HelloReply(reply = "Welcome, ${request.name}"))
+  }
+
+  override suspend fun lotsOfGreetings(
+    requests: Flow<HelloRequest>
+  ): HelloReply {
+    val names = requests.toList().joinToString(", ") { it.name }
+    return HelloReply(reply = names)
+  }
+
+  override fun chat(requests: Flow<HelloRequest>): Flow<HelloReply> =
+    requests.map { request ->
+      HelloReply(reply = "Hello, ${request.name}")
+    }
+}
+```
+
+Generated clients expose the matching coroutine and Flow APIs:
+
+```kotlin
+import demo.greeter.HelloRequest
+import kotlinx.coroutines.flow.flowOf
+
+stub.lotsOfReplies(HelloRequest(name = "Fory")).collect { reply ->
+  println(reply.reply)
+}
+
+val summary = stub.lotsOfGreetings(
+  flowOf(
+    HelloRequest(name = "Ada"),
+    HelloRequest(name = "Grace"),
+  )
+)
+println(summary.reply)
+
+stub.chat(
+  flowOf(
+    HelloRequest(name = "Fory"),
+    HelloRequest(name = "RPC"),
+  )
+).collect { reply ->
+  println(reply.reply)
+}
+```
+
+## Operations
+
+The generated service code only replaces request and response serialization.
+All normal gRPC operational features still belong to grpc-java and
+grpc-kotlin:
+
+- Deadlines and cancellations
+- TLS and authentication
+- Name resolution and load balancing
+- Client and server interceptors
+- Status codes and metadata
+- Channel pooling and lifecycle management
+
 ## Interoperability
 
 Generated Kotlin service companions use Fory binary payloads inside gRPC
@@ -158,22 +257,22 @@ messages.
 
 ## Troubleshooting
 
-**Generated service file is missing**
+### Generated service file is missing
 
 Pass `--grpc` together with `--kotlin_out`. Schemas without service definitions
 only generate model files and the schema module.
 
-**Serializer class not found at runtime**
+### Serializer class not found at runtime
 
 Ensure KSP runs for the generated Kotlin model sources and that
 `fory-kotlin-ksp` uses the same Fory version as `fory-kotlin`.
 
-**gRPC classes are unresolved**
+### gRPC classes are unresolved
 
 Add grpc-java and grpc-kotlin dependencies to the application module. Fory
 Kotlin artifacts do not add those dependencies automatically.
 
-**A protobuf client cannot read responses**
+### A protobuf client cannot read responses
 
 Fory gRPC uses Fory binary protocol payloads, not protobuf wire-format 
messages.
 Use generated Fory gRPC companions on both sides for the same service schema.
diff --git a/docs/guide/python/grpc-support.md 
b/docs/guide/python/grpc-support.md
index c5106f91b..cdcff9224 100644
--- a/docs/guide/python/grpc-support.md
+++ b/docs/guide/python/grpc-support.md
@@ -28,6 +28,15 @@ IDL, or FlatBuffers IDL and you want gRPC transport 
semantics with Fory payload
 encoding. Use standard protobuf gRPC code generation when clients or tools must
 consume protobuf message bytes directly.
 
+Generated Python companions currently target the synchronous `grpcio` API. Use
+regular `def` servicer methods, `grpc.server(...)`, standard `grpc.Channel`
+instances, and Python iterators or generators for streaming RPCs. The generated
+stub accepts any channel configured by your application. The compiler does not
+generate `grpc.aio` stubs or service bases, so do not implement generated
+servicer methods as `async def` unless you add a custom adapter outside the
+generated companion. Python gRPC async support based on `grpc.aio` will be
+available in the next Fory release.
+
 ## Install Dependencies
 
 Install `grpcio` alongside `pyfory`. The generated companion imports `grpc`, 
but
@@ -112,7 +121,8 @@ so service implementations do not perform manual Fory 
registration.
 
 ## Create a Client
 
-Use the generated stub with a normal `grpcio` channel:
+Use the generated stub with a normal `grpcio` channel. Production clients
+usually pass a TLS/auth-configured channel:
 
 ```python
 import grpc
@@ -122,7 +132,8 @@ import demo_greeter_grpc
 
 
 def main():
-    with grpc.insecure_channel("localhost:50051") as channel:
+    credentials = grpc.ssl_channel_credentials()
+    with grpc.secure_channel("api.example.com:443", credentials) as channel:
         stub = demo_greeter_grpc.GreeterStub(channel)
         reply = stub.say_hello(demo_greeter.HelloRequest(name="Fory"))
         print(reply.reply)
@@ -132,6 +143,14 @@ if __name__ == "__main__":
     main()
 ```
 
+For local tests and development, an insecure channel can be used explicitly:
+
+```python
+# Test-only channel. Use a TLS/auth-configured grpc.Channel in production.
+with grpc.insecure_channel("localhost:50051") as channel:
+    stub = demo_greeter_grpc.GreeterStub(channel)
+```
+
 `grpcio` still owns channel options, credentials, deadlines, metadata, retries,
 and interceptors.
 
@@ -151,22 +170,58 @@ service Greeter {
 
 Generated Python code follows `grpcio` conventions:
 
-- Unary stubs call `channel.unary_unary(...)`.
-- Server-streaming stubs return an iterator over response objects.
-- Client-streaming stubs accept an iterator of request objects.
-- Bidirectional stubs accept a request iterator and return a response iterator.
-- Servicer methods use snake_case names and return either a single response or
-  an iterator, depending on the streaming shape.
+| IDL shape                                 | Servicer method shape            
           | Stub method shape                |
+| ----------------------------------------- | 
------------------------------------------- | -------------------------------- |
+| `rpc A (Req) returns (Res)`               | returns one response object      
           | returns one response object      |
+| `rpc A (Req) returns (stream Res)`        | yields response objects          
           | returns an iterator of responses |
+| `rpc A (stream Req) returns (Res)`        | consumes an iterator and returns 
a response | accepts an iterator of requests  |
+| `rpc A (stream Req) returns (stream Res)` | consumes and yields iterators    
           | accepts and returns iterators    |
 
-Example server-streaming implementation:
+Servicer methods use snake_case names, while generated descriptors preserve the
+exact IDL service and method names for the gRPC path.
+
+Server implementations can use Python iterators directly:
 
 ```python
 class Greeter(demo_greeter_grpc.GreeterServicer):
     def lots_of_replies(self, request, context):
-        for index in range(3):
-            yield demo_greeter.HelloReply(
-                reply=f"Hello {request.name}, response {index}"
-            )
+        yield demo_greeter.HelloReply(reply=f"Hello, {request.name}")
+        yield demo_greeter.HelloReply(reply=f"Welcome, {request.name}")
+
+    def lots_of_greetings(self, request_iterator, context):
+        names = [request.name for request in request_iterator]
+        return demo_greeter.HelloReply(reply=", ".join(names))
+
+    def chat(self, request_iterator, context):
+        for request in request_iterator:
+            yield demo_greeter.HelloReply(reply=f"Hello, {request.name}")
+```
+
+Generated clients use the standard `grpcio` streaming call shapes:
+
+```python
+credentials = grpc.ssl_channel_credentials()
+with grpc.secure_channel("api.example.com:443", credentials) as channel:
+    stub = demo_greeter_grpc.GreeterStub(channel)
+
+    for reply in stub.lots_of_replies(
+        demo_greeter.HelloRequest(name="Fory")
+    ):
+        print(reply.reply)
+
+    def greeting_requests():
+        yield demo_greeter.HelloRequest(name="Ada")
+        yield demo_greeter.HelloRequest(name="Grace")
+
+    summary = stub.lots_of_greetings(greeting_requests())
+    print(summary.reply)
+
+    def chat_requests():
+        yield demo_greeter.HelloRequest(name="Fory")
+        yield demo_greeter.HelloRequest(name="RPC")
+
+    for reply in stub.chat(chat_requests()):
+        print(reply.reply)
 ```
 
 ## Operations
diff --git a/docs/guide/rust/grpc-support.md b/docs/guide/rust/grpc-support.md
index ed636344a..4c9ca55f6 100644
--- a/docs/guide/rust/grpc-support.md
+++ b/docs/guide/rust/grpc-support.md
@@ -33,7 +33,7 @@ consume protobuf message bytes directly.
 Add `tonic` and `bytes` to the crate that compiles the generated service files.
 Fory Rust crates do not add gRPC as a hard dependency. Add `tokio` for async
 servers and clients, and `tokio-stream` when your service implementation needs
-to build streaming responses.
+to build streaming responses or request streams.
 
 ```toml
 [dependencies]
@@ -180,8 +180,117 @@ Generated Rust code follows tonic conventions:
 - The generated codec is used for every message frame, including streaming
   frames.
 
-Use the generated trait signatures as the source of truth for the concrete
-associated stream types in your service implementation.
+Use the generated trait signatures as the source of truth for concrete
+associated stream types in your service implementation:
+
+```rust
+use demo_greeter::{HelloReply, HelloRequest};
+use demo_greeter_service::Greeter;
+use std::pin::Pin;
+use tokio_stream::{self as stream, Stream, StreamExt};
+use tonic::{Request, Response, Status};
+
+#[derive(Default)]
+struct MyGreeter;
+
+type ReplyStream =
+    Pin<Box<dyn Stream<Item = Result<HelloReply, Status>> + Send + 'static>>;
+
+#[tonic::async_trait]
+impl Greeter for MyGreeter {
+    type LotsOfRepliesStream = ReplyStream;
+    type ChatStream = ReplyStream;
+
+    async fn lots_of_replies(
+        &self,
+        request: Request<HelloRequest>,
+    ) -> Result<Response<Self::LotsOfRepliesStream>, Status> {
+        let name = request.into_inner().name;
+        let replies = vec![
+            Ok(HelloReply {
+                reply: format!("Hello, {name}"),
+            }),
+            Ok(HelloReply {
+                reply: format!("Welcome, {name}"),
+            }),
+        ];
+        Ok(Response::new(Box::pin(stream::iter(replies))))
+    }
+
+    async fn lots_of_greetings(
+        &self,
+        request: Request<tonic::Streaming<HelloRequest>>,
+    ) -> Result<Response<HelloReply>, Status> {
+        let mut requests = request.into_inner();
+        let mut names = Vec::new();
+        while let Some(request) = requests.next().await {
+            names.push(request?.name);
+        }
+        Ok(Response::new(HelloReply {
+            reply: names.join(", "),
+        }))
+    }
+
+    async fn chat(
+        &self,
+        request: Request<tonic::Streaming<HelloRequest>>,
+    ) -> Result<Response<Self::ChatStream>, Status> {
+        let replies = request.into_inner().map(|request| {
+            request.map(|request| HelloReply {
+                reply: format!("Hello, {}", request.name),
+            })
+        });
+        Ok(Response::new(Box::pin(replies)))
+    }
+}
+```
+
+Generated clients return tonic streaming responses:
+
+```rust
+use demo_greeter::HelloRequest;
+use demo_greeter_service_grpc::greeter_client::GreeterClient;
+use tokio_stream as stream;
+
+let mut client = GreeterClient::connect("http://[::1]:50051";).await?;
+
+let mut replies = client
+    .lots_of_replies(HelloRequest {
+        name: "Fory".to_string(),
+    })
+    .await?
+    .into_inner();
+while let Some(reply) = replies.message().await? {
+    println!("{}", reply.reply);
+}
+
+let greetings = stream::iter(vec![
+    HelloRequest {
+        name: "Ada".to_string(),
+    },
+    HelloRequest {
+        name: "Grace".to_string(),
+    },
+]);
+let summary = client.lots_of_greetings(greetings).await?.into_inner();
+println!("{}", summary.reply);
+
+let chat_requests = stream::iter(vec![
+    HelloRequest {
+        name: "Fory".to_string(),
+    },
+    HelloRequest {
+        name: "RPC".to_string(),
+    },
+]);
+let mut chat = client.chat(chat_requests).await?.into_inner();
+while let Some(reply) = chat.message().await? {
+    println!("{}", reply.reply);
+}
+```
+
+The generated descriptors preserve the exact IDL service and method names for
+the gRPC path.
 
 ## Thread Safety and Payload Types
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to