gRPC and its idea to describe an API in a standardized file, which can generate both client and server code to interact in different languages is a compelling idea.
In this post, I would like to have a quick look at the experience you would have with gRPC streaming capability and the new C# 8 async streams, which sounds like a perfect match.
I am using the .NET Core CLI to create the solution with two projects, one for the server called grpcAsyncStreamServer and one for the client grpcAsyncStreamClient. By the way, do you know you can get tab completion of .NET Core CLI commands? Very handy.
Server
I am using the default gRPC .NET Core template to generate the server part. The template creates a greet.proto file which I will duplicate between the server and the client project. As I want to experience with the streaming capability of gRPC, I am modifying the greet.proto file adding the keyword stream in front of the SayHello HelloReply response.
Server streaming RPC
A server-streaming RPC is similar to our simple example, except the server sends back a stream of responses after getting the client’s request message. After sending back all its responses, the server’s status details (status code and optional status message) and optional trailing metadata are sent back to complete on the server side. The client completes once it has all the server’s responses.
Here is how the greet.proto looks like.
1 | syntax = "proto3"; |
I modify the code of the GreeterService class coming from the template to stream 10 HelloReply back to the client, with a small delay of 200ms in between each string returned to simulate some work.
1 | public class GreeterService : Greeter.GreeterBase |
Client
For the client, I am creating a new Console application and copying the greet.proto into a new folder which I name Protos. Then I need to add the dependencies that you can see on the following csproj, so that at compilation time, the proto file is projected to C# code which I can use in my code. That’s nice because it means that you also get after a first compilation IntelliSense auto-completion.
1 | <Project Sdk="Microsoft.NET.Sdk"> |
We can now use the new C# 8 Async stream to iterate on the server answers asynchronously.
C# has support for iterator methods and async methods, but no support for a method that is both an iterator and an async method. We should rectify this by allowing for await to be used in a new form of async iterator, one that returns an IAsyncEnumerable
The code is greatly readable with this.
1 | static class Program |
Conclusion
We have seen that C# 8 Async streams are nicely integrating with gRPC streaming capabilities. And it makes code more readable!
You can get all the code on GitHub