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
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python3
import sys
import json
def main():
# Your implementation here
for line in sys.stdin:
msg = json.loads(line)
print(json.dumps(msg), flush=True)
if __name__ == "__main__":
main()