The demo broker
One Redpanda in a container, and one Python file that fills it with eleven topics. A twelfth name is kept absent on purpose. The data is the same 2 400 fictional ACME partners the REST demo API serves. Every screen of the Kafka page reads it.
It ships with the repo. Two commands start and fill it:
docker compose -f docs/connectors/kafka/demo/docker-compose.yml up -d
python3 docs/connectors/kafka/demo/acme-topics.py
▸ created acme.partners
▸ created acme.orders
▸ created acme.partners-drift
▸ created acme.partners-poison
▸ created acme.partners-compacted
▸ created acme.partners-reserved
▸ created acme.partners-raw
▸ created acme.probes
▸ created acme.partners-trimmed
▸ created acme.empty
▸ created acme.live
✓ filled
✓ twelve topics as declared (acme.absent is absent)
The script needs the Kafka client for Python: python3 -m pip install confluent-kafka.
The topics
A partner has the same name and city here and on the REST demo. Each topic serves one section of the Kafka page:
| Topic | Shape | Used by |
|---|---|---|
acme.partners |
2 400 JSON objects, one partition | Quickstart |
acme.orders |
24 000 orders, keyed by partner over six partitions | Partitions and the cursor |
acme.partners-drift |
2 400, and two new fields appear at message 1 201 | Schema evolution |
acme.partners-poison |
1 000, of which 143 are not a JSON object | Poison messages |
acme.partners-compacted |
cleanup.policy=compact; 1 000 rows then 300 tombstones |
Tombstones |
acme.partners-reserved |
500, each carrying a top-level id — the REST record verbatim |
Seven reserved names |
acme.partners-raw |
500 with Partner Name, credit.limit, MONTANT_€, an object and an array |
Names the producer chose |
acme.probes |
500 ChirpStack events: 450 up with the reading under object, 50 status; one reading is the text sensor-fault |
A value nested in the message |
acme.partners-trimmed |
5 000, and trim moves its log start on demand |
A log that moved under the cursor |
acme.empty |
created, zero messages | An empty poll |
acme.live |
empty until feed writes to it while a run reads |
The head is the target |
acme.absent |
never created | A topic that does not exist |
The poison messages (a truncated object, a JSON array, a JSON scalar) sit at fixed places, so every fill gives the same counts.
The three gestures that change the broker
These three write to the broker; the Kafka page says when to use each:
python3 docs/connectors/kafka/demo/acme-topics.py feed --rate 200 --seconds 30 # a producer racing the run, on acme.live
python3 docs/connectors/kafka/demo/acme-topics.py feed --topic acme.partners-trimmed --rate 500 --seconds 2
python3 docs/connectors/kafka/demo/acme-topics.py trim 5500 # acme.partners-trimmed: offsets 0..5499 are gone
trim moves the partition's log start at once, as retention would over days. It runs rpk in
the container lumnik-demo-redpanda. Set KAFKA_DEMO_CONTAINER to use another one.
Checking it before you blame the manifest
python3 docs/connectors/kafka/demo/acme-topics.py verify
It checks every topic's count and partitions, and that acme.absent does not exist. After trim,
or feed --topic acme.partners-trimmed, verify reports acme.partners-trimmed: expected.
reset drops the topics and fills them again:
python3 docs/connectors/kafka/demo/acme-topics.py reset
Reset the hub's cursors too. With the old cursor, a run on a refilled topic reads nothing and
completes. After reset, for each connector to read from the start:
lm endpoint reset-cursor <connector>/default
host.docker.internal:29092, not localhost:19092
- Your shell (and
acme-topics.py) reaches the broker atlocalhost:19092. - The hub, in its container, reaches it at
host.docker.internal:29092— what the manifests carry. The wrong listener ends in the broker timeout after about 60 s.
Check both:
docker exec lumnik-demo-redpanda rpk cluster info --brokers localhost:9092
docker compose -f docker-compose.selfhost.yml exec hub bash -c 'exec 3<>/dev/tcp/host.docker.internal/29092 && echo REACHABLE'
What it is not
- Automatic topic creation is off, so
acme.absentstays absent. - Authenticates nobody. Every topic is plaintext. The
sasl-plainmanifest on the Kafka page shows its refusals, not a successful handshake. - A throwaway rig. One node, no replication, no persistence to count on.