Sum Numbers - Client Streaming RPC
This example demonstrates client streaming RPC, where the client sends multiple requests and receives a single response after all requests are processed.
What You'll Learn
- Defining a proto service with client streaming RPC
- Implementing a client streaming handler using
ClientStream{T} - Iterating over incoming requests
- Returning a single aggregated response
Proto Definition
// sum.proto
syntax = "proto3";
package math;
service Math {
// Client streaming: stream of requests → single response
rpc Sum (stream SumRequest) returns (SumResponse);
}
message SumRequest {
double value = 1;
}
message SumResponse {
double total = 1;
int32 count = 2;
}The stream keyword before SumRequest indicates the client sends multiple messages.
Server Implementation
using gRPCServer# Include generated typesinclude("generated/math/math.jl")using .math# Client streaming handler - receives multiple requests, returns single responsefunction sum_handler(ctx::ServerContext, stream::ClientStream{SumRequest}) total = 0.0 count = 0 @info "Starting to receive numbers" request_id=ctx.request_id for request in stream if is_cancelled(ctx) @warn "Stream cancelled by client" break end total += request.value count += 1 @debug "Received value" value=request.value running_total=total end @info "Sum complete" total=total count=count request_id=ctx.request_id return SumResponse(total, count)end# Register the service with the codegen registration functionfunction main() host = "127.0.0.1" port = 50053 server = GRPCServer(host, port; enable_health_check = true, enable_reflection = true ) register_Math!(server; Sum = sum_handler) @info "gRPC server starting (client streaming example)" host=host port=port run(server)endmain()Equivalent form — the per-RPC do-block registration:
register_Math_Sum!(server) do ctx, stream total = 0.0 for request in stream total += request.value end SumResponse(total, 0)endKey Concepts
Client Streaming Handler Signature
function handler(ctx::ServerContext, stream::ClientStream{RequestType}) for request in stream # Process each request end return ResponseType(...) # Single responseend- Receives
ClientStream{T}instead of a single request - Iterates over stream with
for request in stream - Returns response directly (not via stream)
- Check
is_cancelled(ctx)to stop early if the client disconnects
Registration
The generated register_Math! accepts the handler as Sum = sum_handler; handler signatures are validated at registration time. The generated client stub for this RPC is Math_Sum_Client.
Testing
Run the Server
cd examples/03_sum_numbers
julia --project=../.. server.jlStream Numbers with grpcurl
Client streaming requires stdin piping:
echo '{"value": 1}
{"value": 2}
{"value": 3}
{"value": 4}
{"value": 5}' | grpcurl -plaintext -d @ localhost:50053 math.Math/SumExpected output:
{
"total": 15,
"count": 5
}Empty Stream
echo '' | grpcurl -plaintext -d @ localhost:50053 math.Math/SumReturns {"total": 0, "count": 0}.
Use Cases
Client streaming is ideal for:
- Batch uploads: Sending multiple records and getting a summary
- Aggregation: Computing statistics over streamed data
- File uploads: Streaming file chunks and getting confirmation
- Sensor data: Collecting measurements and returning analysis
Next Steps
Proceed to Chat to learn about bidirectional streaming, where both client and server send multiple messages.