env-04-kv-quorum
0.000
Challenge · difficulty 5/5
# Quorum-replicated key-value store Three replica nodes (`peer0`, `peer1`, `peer2`) form a key-value store with **N=3, W=2, R=2** (W+R>N, so a quorum read always observes the latest quorum write). A separate `client` drives it. Implement the replica program (`peer.go`) and the `client.go` so that: - A **PUT** to any replica (the coordinator) stores the value and replicates it to a **write quorum of W=2** replicas (itself + one peer), then acknowledges. It must NOT assume every replica gets a copy. - A **GET** from any replica performs a **quorum read (R=2)** across replicas and returns the value with the highest version — so a replica that did not receive a particular write still returns the correct value. - The client must: PUT `k1=alpha` via `peer0`, PUT `k2=beta` via `peer1`, then GET both `k1` and `k2` **from `peer2`**, and write them to `result.txt` as: ``` k1=alpha k2=beta ``` `peer2` will be the replica left without those keys, so reading them back from `peer2` only succeeds with a working quorum read. Use only the Go standard library (`net/http`). Discovery contract: `PORT` (your listen port) and `PEER_<NAME>_HOST` / `PEER_<NAME>_PORT` for peers.
Proposed solution
[turn 1] list_nodes({}) -> {"nodes": [{"name": "peer0", "provides": "go run .", "ports": [7000], "needs": ["peer1", "peer2"]}, {"name": "peer1", "provides": "go run .", "ports": [7000], "needs": ["peer0", "peer2"]}, {"name": "p
[turn 2] write_file({"node": "peer0", "path": "main.go", "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n)\n\) -> {"ok": true, "node": "peer0", "path": "main.go"}
[turn 3] write_file({"node": "peer1", "path": "main.go", "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n)\n\ntype Entry str) -> {"ok": true, "node": "peer1", "path": "main.go"}
[turn 4] write_file({"node": "peer2", "path": "main.go", "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n)\n\ntype Entry str) -> {"ok": true, "node": "peer2", "path": "main.go"}
[turn 5] write_file({"node": "client", "path": "main.go", "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"time\"\n)\n\ntype Entry stru) -> {"ok": true, "node": "client", "path": "main.go"}
[turn 6] verify({}) -> {"passed": false, "checks": [{"name": "quorum read on a non-replica node returned both writes", "ok": false, "detail": "client wrote ''; want 'k1=alpha\\nk2=beta'"}], "launch_errors": ["peer0:7000 nev
[turn 7] run({"node": "peer0", "cmd": "go run ."}) -> {"rc": 1, "output": "go: go.mod file not found in current directory or any parent directory; see 'go help modules'\n"}
[turn 8] write_file({"node": "peer0", "path": "go.mod", "content": "module peer0\n\ngo 1.21"}) -> {"ok": true, "node": "peer0", "path": "go.mod"}
[turn 9] write_file({"node": "peer1", "path": "go.mod", "content": "module peer1\n\ngo 1.21"}) -> {"ok": true, "node": "peer1", "path": "go.mod"}
[turn 10] write_file({"node": "peer2", "path": "go.mod", "content": "module peer2\n\ngo 1.21"}) -> {"ok": true, "node": "peer2", "path": "go.mod"}
[turn 11] write_file({"node": "client", "path": "go.mod", "content": "module client\n\ngo 1.21"}) -> {"ok": true, "node": "client", "path": "go.mod"}
[turn 12] run({"node": "peer0", "cmd": "go run . 2>&1 | head -20"}) -> {"rc": 0, "output": "# peer0\n./main.go:10:2: \"strconv\" imported and not used\n"}
[turn 13] write_file({"node": "peer0", "path": "main.go", "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n)\n\ntype Entry str) -> {"ok": true, "node": "peer0", "path": "main.go"}
[turn 14] write_file({"node": "peer1", "path": "main.go", "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n)\n\ntype Entry str) -> {"ok": true, "node": "peer1", "path": "main.go"}