快速开始Getting started
从零到一条消息被发出去、又被读回来。
From nothing to a message produced and read back.
前置条件Prerequisites
- 最新稳定版的 MoonBit 工具链;
- 原生 C 编译环境,以及 zlib——
cmd/main/moon.pkg为 native 目标设置了cc-link-flags = "-lz"; - 一个 Apache Kafka 4.x KRaft 集群。可以用仓库附带的 compose 配置起一个单节点 broker(需要容器运行时),也可以指向你自己已有的集群。
- A recent stable MoonBit toolchain;
- A native C toolchain plus zlib —
cmd/main/moon.pkgsetscc-link-flags = "-lz"for the native target; - An Apache Kafka 4.x KRaft cluster. Either bring up the single-node broker from the bundled compose file (needs a container runtime), or point the CLI at a cluster you already run.
native 目标,两个包都声明了
supported_targets = "+native"。省略 --target native 会在构建期失败。
native target only, and
both packages declare supported_targets = "+native". Omitting
--target native fails at build time.
启动本地 KafkaStart a local Kafka
仓库附带的配置与 moonkafka 主仓库一致:单节点、KRaft 模式、监听
9092,容器名为 moonkafka-demo-kafka,镜像
apache/kafka:4.3.0。
The bundled configuration matches the moonkafka repository: a single node in
KRaft mode listening on 9092, container
moonkafka-demo-kafka, image apache/kafka:4.3.0.
docker compose -f docker-compose.kafka.yml up -d
容器自带健康检查,每 5 秒执行一次
kafka-topics.sh --bootstrap-server localhost:9092 --list,
命令成功即视为就绪。等它就绪后创建演示主题:
The container healthchecks itself every 5 seconds by running
kafka-topics.sh --bootstrap-server localhost:9092 --list; the
first success means it is ready. Once it is, create the demo topic:
docker exec moonkafka-demo-kafka /opt/kafka/bin/kafka-topics.sh \
--bootstrap-server localhost:9092 \
--create --if-not-exists \
--topic events \
--partitions 3 \
--replication-factor 1
produce 会失败,
consume 同样如此。请先按上面的命令建好主题,或让 broker 的自动建主题
策略处理。
构建Build
moon build --target native
产物是 native 调试构建的可执行文件,路径为
_build/native/debug/build/cmd/main/main.exe。集成测试默认直接执行这个
二进制,因此它也是 harness 期望的路径。
This produces the native debug executable at
_build/native/debug/build/cmd/main/main.exe — the same path the
integration test executes by default.
跑通第一条消息A first round trip
先在终端 A 启动 consumer。consume 会持续轮询,直到你用
Ctrl-C 停掉它,或者用 --max-messages 让它读够 n 条后正常退出。
Start the consumer in terminal A first. consume keeps polling
until you stop it with Ctrl-C, or until --max-messages
lets it exit cleanly after n records.
moon run --target native cmd/main -- consume events
它会先打印一行说明,然后开始输出记录:
It prints one line describing the session, then starts emitting records:
consuming topic "events" from 127.0.0.1:9092; press Ctrl-C to stop
offset=0 timestamp=1757923200000 key=demo-key value=Hello from MoonBit
然后在终端 B 发送一条消息:
Then send a message from terminal B:
终端 BTerminal Bmoon run --target native cmd/main -- produce events "Hello from MoonBit" demo-key
producer 等待 broker 确认后,打印它写入的偏移量:
The producer waits for the broker to acknowledge and prints the offset it wrote to:
sent to topic "events" at offset 0
--max-messages 1,consumer 打印完这一条就正常退出(退出码 0),
适合写脚本。这也是集成测试用的方式。
--max-messages 1 and the consumer exits cleanly (code 0) right
after printing that record — handy in scripts, and exactly what the
integration test does.
用 make 跑Driving it with make
Makefile 把日常命令收成目标。直接运行 make 会打印目标列表。
The Makefile collects the day-to-day commands into targets.
Running bare make prints the list.
| 目标 | 作用 |
|---|---|
make check | 类型检查,不做代码生成——最快的反馈 |
make check-strict | 同上,但把警告视为错误;CI 用的就是它 |
make test | 运行测试套件(native) |
make build | 构建 native CLI |
make fmt | 就地格式化 MoonBit 源码 |
make fmt-check | 只检查格式,不写入;有文件会被改动即失败 |
make ci | check-strict + build + test + fmt-check |
make itest | 端到端集成测试:容器起 Kafka 再驱动真实 CLI |
make itest-plan | 只打印集成测试将要执行的命令,不启动任何东西 |
make kafka-up | 用 compose 启动 Kafka |
make kafka-down | 停止那个 Kafka |
make run-producer | 发送一条消息:make run-producer VALUE="hello" |
make run-consumer | 消费主题直到 Ctrl-C |
make clean | 删除构建产物 |
| Target | What it does |
|---|---|
make check | Type-check without code generation — the fast feedback loop |
make check-strict | The same, but warnings are errors; what CI gates on |
make test | Run the test suite (native) |
make build | Build the native CLI |
make fmt | Format MoonBit sources in place |
make fmt-check | Verify formatting without writing; fails if any file would change |
make ci | check-strict + build + test + fmt-check |
make itest | End-to-end test: start Kafka in a container, drive the real CLI |
make itest-plan | Print what the integration test would run, without starting anything |
make kafka-up | Start Kafka via compose |
make kafka-down | Stop that Kafka |
make run-producer | Send one message: make run-producer VALUE="hello" |
make run-consumer | Consume the topic until Ctrl-C |
make clean | Remove build artifacts |
持续集成Continuous integration
.github/workflows/ci.yml 在 push(main、develop)
和每个 pull request 上依次跑上面这几个目标:检查、构建、测试、格式检查。
集成测试不在这里跑——它需要容器运行时和一个真实 broker。
.github/workflows/ci.yml runs the targets above in order —
check, build, test, formatting — on every push to main or
develop and on every pull request. The integration test is
not part of it: that one needs a container runtime and a live broker.
可覆盖的变量Overridable variables
所有变量都可以在命令行上覆盖,例如 make run-producer VALUE=hi TOPIC=orders。
Every variable can be overridden on the command line, e.g. make run-producer VALUE=hi TOPIC=orders.
| 变量 | 默认值 | 说明 |
|---|---|---|
MOON | moon | moon 可执行文件 |
TARGET | native | 构建目标 |
PKG | cmd/main | 要运行 / 构建的包 |
TOPIC | events | 演示主题 |
HOST | 127.0.0.1 | broker 地址 |
PORT | 9092 | broker 端口 |
KEY | demo-key | run-producer 的消息 key |
START | earliest | run-consumer 的起始位置 |
RUNTIME | 自动探测(podman 优先) | kafka-up / kafka-down 使用的引擎 |
ITEST_RUNTIME | docker | make itest 固定使用的引擎 |
ITEST_FLAGS | 空 | 追加给集成测试的参数,如 --keep |
| Variable | Default | Meaning |
|---|---|---|
MOON | moon | The moon executable |
TARGET | native | Build target |
PKG | cmd/main | Package to run or build |
TOPIC | events | Demo topic |
HOST | 127.0.0.1 | Broker host |
PORT | 9092 | Broker port |
KEY | demo-key | Message key for run-producer |
START | earliest | Start position for run-consumer |
RUNTIME | auto-detected (podman first) | Engine used by kafka-up / kafka-down |
ITEST_RUNTIME | docker | Engine make itest is pinned to |
ITEST_FLAGS | empty | Extra flags for the integration test, e.g. --keep |
RUNTIME 只影响 kafka-up / kafka-down
这两个手动开关,默认走自动探测。ITEST_RUNTIME 只影响
make itest,默认固定 docker——因为集成测试自己的探测会
逐个候选尝试并打印「不可用」的中间日志。两者的原因见
集成测试。
RUNTIME only affects the manual kafka-up /
kafka-down helpers and auto-detects by default.
ITEST_RUNTIME only affects make itest and is pinned to
docker, because the harness's own probe walks its candidates and
logs each miss. See Integration test for why.
便捷目标Convenience targets
make run-producer VALUE="hello" TOPIC=events KEY=demo-key
make run-consumer TOPIC=events START=latest
run-producer 在缺少 VALUE 时会打印用法并以退出码 2 结束。
run-producer prints its usage and exits 2 when VALUE is missing.
停止 KafkaStop Kafka
docker compose -f docker-compose.kafka.yml down