ARCHIVED from builddistributedsystem.com on 2026-04-28 — URL: https://builddistributedsystem.com/tracks/networker/tasks/task-5-3-2-grpc-unary
TASK

Implementation

Implement a gRPC-style unary RPC service. In unary RPC, the client sends exactly one request and receives exactly one response.

gRPC message format on the wire:
[compressed_flag: 1 byte][message_length: 4 bytes][protobuf_message]

Implement a simple KeyValue service:

Request:  {"type": "grpc_call", "msg_id": 1, "service": "KeyValue", "method": "Get", "request": {"key": "user:1"}}
Response: {"type": "grpc_call_ok", "in_reply_to": 1, "status": "OK", "response": {"key": "user:1", "value": "Alice", "found": true}}

Request:  {"type": "grpc_call", "msg_id": 2, "service": "KeyValue", "method": "Put", "request": {"key": "user:2", "value": "Bob"}}
Response: {"type": "grpc_call_ok", "in_reply_to": 2, "status": "OK", "response": {"written": true}}

Request:  {"type": "grpc_call", "msg_id": 3, "service": "KeyValue", "method": "Get", "request": {"key": "missing"}}
Response: {"type": "grpc_call_ok", "in_reply_to": 3, "status": "NOT_FOUND", "response": {"key": "missing", "found": false}}

Sample Test Cases

Put and Get a keyTimeout: 5000ms
Input
{"src":"c0","dest":"n1","body":{"type":"init","msg_id":1,"node_id":"n1","node_ids":["n1"]}}
{"src":"c1","dest":"n1","body":{"type":"grpc_call","msg_id":2,"service":"KeyValue","method":"Put","request":{"key":"k1","value":"v1"}}}
{"src":"c1","dest":"n1","body":{"type":"grpc_call","msg_id":3,"service":"KeyValue","method":"Get","request":{"key":"k1"}}}
Expected Output
{"src": "n1", "dest": "c0", "body": {"type": "init_ok", "in_reply_to": 1, "msg_id": 0}}
{"src": "n1", "dest": "c1", "body": {"type": "grpc_call_ok", "in_reply_to": 2, "status": "OK", "response": {"written": true}, "msg_id": 1}}
{"src": "n1", "dest": "c1", "body": {"type": "grpc_call_ok", "in_reply_to": 3, "status": "OK", "response": {"key": "k1", "value": "v1", "found": true}, "msg_id": 2}}
Get missing key returns NOT_FOUNDTimeout: 5000ms
Input
{"src":"c0","dest":"n1","body":{"type":"init","msg_id":1,"node_id":"n1","node_ids":["n1"]}}
{"src":"c1","dest":"n1","body":{"type":"grpc_call","msg_id":2,"service":"KeyValue","method":"Get","request":{"key":"missing"}}}
Expected Output
{"src": "n1", "dest": "c0", "body": {"type": "init_ok", "in_reply_to": 1, "msg_id": 0}}
{"src": "n1", "dest": "c1", "body": {"type": "grpc_call_ok", "in_reply_to": 2, "status": "NOT_FOUND", "response": {"key": "missing", "found": false}, "msg_id": 1}}

Hints

Hint 1
Unary RPC: client sends one request, server sends one response
Hint 2
gRPC uses HTTP/2 as its transport protocol
Hint 3
Each RPC method maps to a (service, method) pair
Hint 4
The request and response are protobuf-encoded messages
Hint 5
gRPC adds a 5-byte header: 1 byte compressed flag + 4 bytes message length
OVERVIEW

Theoretical Hub

Concept overview coming soon

Key Concepts

gRPCunary RPCHTTP/2service definitionstub
main.py
python
Implement a gRPC Unary RPC Service - The Networker | Build Distributed Systems