Implementation
The echo workload is the simplest Maelstrom workload. Clients send echo messages containing a value, and your node must echo that value back.
Request format:
{
"type": "echo",
"msg_id": 1,
"echo": "Please echo 35"
}Expected response:
{
"type": "echo_ok",
"msg_id": 1,
"in_reply_to": 1,
"echo": "Please echo 35"
}Combine your init handling from the previous task with a new echo handler. Your node should handle both message types.
Sample Test Cases
{"src":"c0","dest":"n1","body":{"type":"init","msg_id":1,"node_id":"n1","node_ids":["n1"]}}
{"src":"c1","dest":"n1","body":{"type":"echo","msg_id":2,"echo":"hello"}}
{"src": "n1", "dest": "c0", "body": {"type": "init_ok", "in_reply_to": 1, "msg_id": 0}}
{"src": "n1", "dest": "c1", "body": {"type": "echo_ok", "echo": "hello", "in_reply_to": 2, "msg_id": 1}}
Hints
Hint 1▾
Hint 2▾
Hint 3▾
Theoretical Hub
Remote Procedure Calls (RPC)
Echo is the simplest form of RPC: a client sends a request and expects a response. While trivial, this pattern forms the basis of all distributed communication.
The Request-Response Pattern
Complex systems like Raft are built from many request-response interactions:
Client Server
| |
|------- Request (echo) ------->|
| |
|<------ Response (echo_ok) ----|
| |
Handler Dispatch
Your node needs to dispatch messages to appropriate handlers based on type. This is a pattern you will use throughout:
- Examine the message
typefield - Route to the correct handler function
- Generate and send the appropriate response
Pseudocode
for each message from stdin:
parse JSON
switch message.body.type:
case "init":
store node_id and node_ids
reply with init_ok
case "echo":
reply with echo_ok containing the echo value
default:
log unknown message type
Idempotency
Echo is naturally idempotent - calling it multiple times with the same input produces the same output. This property is valuable in distributed systems where messages may be retried.