115 lines
5.4 KiB
Markdown
115 lines
5.4 KiB
Markdown
# AGENTS.md
|
||
|
||
## Non-negotiables
|
||
|
||
1. 写代码不要猜。先读当前实现、接口、配置和测试,再改。
|
||
2. 不写流水账。文档、注释和总结都要解释边界、决策和可执行动作。
|
||
3. 前端或客户端改动不要添加无意义描述文案。界面文字必须服务真实操作或状态。
|
||
4. 不把房间核心状态扩散到多个服务。Room Cell 仍然是房间状态 owner。
|
||
5. 不把连接态塞进 `room-service`。WebSocket、在线连接和投递属于 `im-service`。
|
||
6. 代码永远保持高密度注释
|
||
|
||
## Architecture Boundaries
|
||
|
||
- `gateway-service` 只做 HTTP 入口、鉴权、协议转换和内部 gRPC 编排。
|
||
- `room-service` 负责 Room Cell、房间状态、麦位、房间 presence、本地榜、snapshot、command log、outbox、Redis lease。
|
||
- `im-service` 负责 WebSocket、session、房间频道、公屏、系统消息、单聊、ACK、最近历史。
|
||
- `wallet-service` 负责账务语义。`SendGift` 必须先扣费成功,再落房间表现。
|
||
- `activity-service` 通过 room outbox 事件消费,不侵入 Room Cell 主链路。
|
||
- `user-service` 负责用户主数据,不应该成为房间高频流程的同步中心。
|
||
|
||
## Persistence Rules
|
||
|
||
- `room-service` 生产路径使用 MySQL repository 和 Redis directory。
|
||
- `memory` repository/directory 只用于单元测试或明确的本地隔离测试。
|
||
- MySQL 是房间恢复的持久来源:`rooms`、`room_snapshots`、`room_command_log`、`room_outbox`。
|
||
- Redis 只保存当前路由/lease 等热状态,不能作为唯一恢复来源。
|
||
- Redis lease 更新必须保持原子性,不能改回非原子的 GET + SET 接管逻辑。
|
||
|
||
## Protocol Rules
|
||
|
||
- 外部 HTTP JSON 入口在 `gateway-service`。
|
||
- `gateway-service` 的 `/api/v1` 业务响应必须使用 `{code,message,request_id,data}` envelope;healthcheck 不套业务响应格式。
|
||
- `request_id` 是链路追踪字段,必须透传到内部 gRPC `RequestMeta.request_id`;不要把它当幂等键使用。
|
||
- 外部 WebSocket JSON 入口在 `im-service`。
|
||
- 内部服务通信统一 gRPC + protobuf。
|
||
- Proto/API 必须保持向后兼容。不能直接删除字段、复用字段编号、修改字段含义、修改已有枚举值语义。
|
||
- 新旧版本会在滚动发布期间同时在线,必须允许旧 `gateway-service` 调新 `room-service`,也必须允许新 `gateway-service` 调旧 `room-service`。
|
||
- 修改 `api/proto` 后必须运行 `make proto`,并提交生成后的 `.pb.go` / `_grpc.pb.go`。
|
||
- 不要在服务之间直接 import 对方 `internal` 包。跨服务只走 protobuf client 或明确的接口抽象。
|
||
|
||
## Compatibility Rules
|
||
以下的注释都是目前不采用的策略,不需要根据这个策略去做
|
||
<!-- - 所有跨服务协议变更必须按“先加字段、双端兼容、灰度发布、确认无旧版本后再清理”的顺序推进。
|
||
- Proto 字段废弃时只能标记 `deprecated` 或保留字段号和字段名,不能直接删除后复用。
|
||
- 枚举只能追加新值,不能改已有数值和语义;旧服务收到未知枚举时必须有安全默认行为。
|
||
- HTTP JSON 请求和响应只能做兼容扩展;不能让旧客户端因为缺少新字段而失败。
|
||
- 数据库变更必须兼容滚动发布。先新增 nullable 字段、默认值或新表,代码同时兼容新旧结构后,再考虑删除旧字段。
|
||
- 数据库字段语义不能原地改写。需要改变语义时新增字段承载新语义,并写清迁移窗口和回滚策略。
|
||
- 删除 proto 字段、API 字段或数据库字段前,必须确认线上没有旧版本实例、旧客户端或旧数据路径依赖。 -->
|
||
|
||
## Port Rules
|
||
|
||
本项目本地端口使用 `13xxx`:
|
||
|
||
- `13000`: gateway HTTP
|
||
- `13001`: room gRPC
|
||
- `13002`: im HTTP/WebSocket
|
||
- `13003`: im gRPC
|
||
- `13004`: wallet gRPC
|
||
- `13005`: user gRPC
|
||
- `13006`: activity gRPC
|
||
- `13306`: local Docker MySQL host port
|
||
- `13379`: local Docker Redis host port
|
||
|
||
不要重新引入 `808x` 作为默认端口。
|
||
|
||
## Coding Rules
|
||
|
||
- 默认使用 Go 标准库和仓库已有小包;不要为了轻量逻辑引入重框架。
|
||
- 手写代码保持高密度有效注释,注释解释工程语义和失败分支,不复述语法。
|
||
- 新增配置必须同时考虑本地 `config.yaml`、Docker `config.docker.yaml`、以及线上配置示例。
|
||
- 新增服务依赖必须在 `docker-compose.yml` 中体现本地可运行形态。
|
||
- 数据库表结构变更必须同步更新 `services/room-service/deploy/mysql/initdb`。
|
||
- 不要把线上密钥、云数据库密码、Redis 密码写进真实配置。只能写占位示例。
|
||
- 保持 `gofmt`,不要手调 Go import 顺序。
|
||
|
||
## Test Expectations
|
||
|
||
改动后至少运行:
|
||
|
||
```bash
|
||
go test ./...
|
||
```
|
||
|
||
涉及 protobuf 时运行:
|
||
|
||
```bash
|
||
make proto
|
||
go test ./...
|
||
```
|
||
|
||
涉及 Docker、端口、服务配置或基础设施时运行:
|
||
|
||
```bash
|
||
docker compose config
|
||
docker compose build
|
||
```
|
||
|
||
涉及启动链路时实际拉起:
|
||
|
||
```bash
|
||
docker compose up -d
|
||
docker compose ps
|
||
docker compose down
|
||
```
|
||
|
||
## Safe Change Checklist
|
||
|
||
- 先确认改的是服务内部逻辑、跨服务契约、配置、还是部署编排。
|
||
- 跨服务字段优先改 protobuf,不要在 HTTP handler 或 WS frame 里偷偷扩字段。
|
||
- 房间状态变更必须经过 Room Cell 命令链路。
|
||
- 需要恢复的关键动作必须写 command log 或 snapshot,不能只改内存。
|
||
- 房间外副作用优先走 outbox,除非是明确的同步主链路依赖。
|
||
- 文档只写当前事实和明确约束,不记录“做了什么”的流水账。
|