env-07-pubsub
1.000
Challenge ยท difficulty 4/5
# Publish/subscribe broker
Four nodes are provisioned on a private, no-internet network. Build a topic-based pub/sub system.
Nodes and the program each one runs:
- **broker** โ create **`broker.py`** (launched as `python broker.py`). Listens on `$PORT` and keeps,
per topic, the **ordered list** of messages published to it. Endpoints:
- `POST /publish` with a JSON body `{"topic": "<name>", "message": "<text>"}` โ append the message
to that topic's list. Respond `200`.
- `GET /messages?topic=<name>` โ respond `200` with that topic's messages so far, **one per line**
in publish order (empty body if the topic has none).
- **publisher** โ create **`publisher.py`** (launched as `python publisher.py`). The broker is at
`PEER_BROKER_HOST`/`PEER_BROKER_PORT`. Publish **exactly this sequence, in this order**:
| topic | message |
|-------|---------|
| `alpha` | `one` |
| `alpha` | `two` |
| `alpha` | `three` |
| `beta` | `red` |
| `beta` | `green` |
Then exit.
- **subscriber_a**, **subscriber_b** โ identical subscribers. Create **`subscriber.py`** (launched as
`python subscriber.py`) on each. A subscriber reads the topic it follows from a file `topic.txt`
in its working directory (already present), then keeps its file `received.txt` up to date with that
topic's messages from the broker โ **one per line, in order**. (Poll the broker periodically; the
publisher may not have sent everything yet.)
The task is solved when each subscriber's `received.txt` contains exactly its topic's messages in
publish order: `subscriber_a` (topic `alpha`) โ `one`,`two`,`three`; `subscriber_b` (topic `beta`)
โ `red`,`green`.
Only the Python standard library is available (no internet, no pip). Retry connections that are
briefly refused while a peer is starting.
Proposed solution
[turn 1] list_nodes({}) -> {"nodes": [{"name": "broker", "provides": "python broker.py", "ports": [9000], "needs": []}, {"name": "subscriber_a", "provides": "python subscriber.py", "ports": [], "needs": ["broker"]}, {"name": "s
[turn 2] write_file({"node": "broker", "path": "broker.py", "content": "import json\nfrom http.server import HTTPServer, BaseHTTPRequestHandler\nfrom urllib.parse import parse_qs, urlparse\n\nclass PubSubHandler(BaseHTTP) -> {"ok": true, "node": "broker", "path": "broker.py"}
[turn 3] write_file({"node": "publisher", "path": "publisher.py", "content": "import json\nimport os\nimport time\nimport urllib.request\nimport urllib.error\n\ndef publish_message(topic, message):\n broker_host = os.) -> {"ok": true, "node": "publisher", "path": "publisher.py"}
[turn 4] write_file({"node": "subscriber_a", "path": "subscriber.py", "content": "import os\nimport time\nimport urllib.request\nimport urllib.error\n\ndef get_topic():\n with open(\"topic.txt\", \"r\") as f:\n ) -> {"ok": true, "node": "subscriber_a", "path": "subscriber.py"}
[turn 5] write_file({"node": "subscriber_b", "path": "subscriber.py", "content": "import os\nimport time\nimport urllib.request\nimport urllib.error\n\ndef get_topic():\n with open(\"topic.txt\", \"r\") as f:\n ) -> {"ok": true, "node": "subscriber_b", "path": "subscriber.py"}
[turn 6] verify({}) -> {"passed": true, "checks": [{"name": "subscriber_a received its topic's messages in order", "ok": true, "detail": "got ['one', 'two', 'three'] want ['one', 'two', 'three']"}, {"name": "subscriber_b re