Lesson 6 · Streaming RPCs
Client streaming
A stream of requests in, one response out — the upload shape.
Your win: explain client streaming, read its Go handler
(Recv loop then SendAndClose), and know when it's the right
choice — anchored to bob's UploadAsset.
The shape: many requests → 1 response
The mirror image of Lesson 5. The client sends a stream of messages; when
it's done, the server returns a single response.1
The stream keyword goes on the request:
rpc UploadAsset(stream UploadAssetRequest) returns (UploadAssetResponse);
The Go handler: receive until EOF, then respond once
internal/bob/services/media/media_modifier.go:166func (svc *MediaModifierService) UploadAsset(
srv bpb.MediaModifierService_UploadAssetServer) error {
for {
req, err := srv.Recv()
if err == io.EOF { break } // client finished sending
if err != nil { return err }
// accumulate this chunk…
}
return srv.SendAndClose(&bpb.UploadAssetResponse{...}) // the one response
}
ctx param (use
srv.Context()). Loop srv.Recv() until io.EOF
(that's how you learn the client is done — recall io.EOF from the Go
course), then finish with one srv.SendAndClose(resp).
When to use it
Client streaming fits when the input is a sequence the server folds into one result: uploading a file in chunks, streaming rows for a bulk import, or aggregating many data points into a summary. You avoid buffering the whole payload in one giant message.
bob's UploadAsset is our client-streaming shape (file chunks →
one asset). Note it's currently a stub returning codes.Unimplemented
(media_modifier.go:166) — the signature is the
teaching value. A fully-wired example is yasuo's
ImportSchools(stream …) (proto/yasuo/v1/imports.proto:66).
None of your three services use client streaming — they're unary.
gRPC — Core concepts (Client streaming) + Go Basics
Core concepts for the lifecycle; the Go Basics tutorial implements a client-streaming
method with the Recv-loop-then-SendAndClose pattern.
Check yourself (from memory)
Q1. In client streaming, the stream keyword is on the…
stream
marks the request: (stream Req) returns (Resp).
Q2. A client-streaming Go handler reads requests with…
Recv() until io.EOF,
then one SendAndClose(resp). No plain request argument.
Q3. Client streaming suits…
UploadAsset.
stream on the request). Go handler:
func(srv X_Server) error — no request/ctx args; loop
req, err := srv.Recv() until io.EOF, accumulate, then
srv.SendAndClose(resp). Repo example: bob's UploadAsset
(media.proto:128 → media_modifier.go:166, currently a stub) and yasuo's
ImportSchools. Good for uploads/batch ingestion.stream.Send(chunk) then
stream.CloseAndRecv())? Ask me.