docs: add workbench migration handoff guide

This commit is contained in:
richjohnrambo
2026-09-14 14:49:19 +08:00
parent c1c11560de
commit 989e365492
+351
View File
@@ -0,0 +1,351 @@
# 工作台迁移对接总结文档
> 更新时间:2026-09-14。本文用于后续开启新的 `im_workbench` 工作树时快速接手,覆盖当前迁移边界、接口、鉴权、中间件配置、Kafka 事件、数据库现状和验收步骤。
## 1. 当前结论
工作台已从 `im_server` 拆到独立仓库 `im_workbench`,当前阶段只拆服务和接口边界,数据库暂不迁移。工作台接口统一走 `/v1/workbench/*`,由网关分流到 `im_workbench`;登录仍由 `im_server` 负责,登录成功后把 Token 会话写入 Redis,`im_workbench` 从 Redis 校验登录态。
当前已完成:
| 项目 | 状态 |
|---|---|
| 独立 Go 工程 | 已完成,仓库:`/Users/youshunlai/go_workspace/im_workbench` |
| 独立启动 | 已完成,默认监听 `:6061` |
| 新路由 `/v1/workbench/*` | 已完成 |
| Redis Token 鉴权 | 已完成 |
| 工作台 Kafka 事件生产 | 已完成 |
| 测试环境中间件配置 | 已更新 |
| 数据库迁移 | 暂不迁移,仍使用租户库 `tinode` |
| `im_server` 旧工作台代码 | 暂保留,等新服务稳定后再删 |
最近关键提交:
| 仓库 | Commit | 说明 |
|---|---|---|
| `im_workbench` | `8b5c5e3` | 兼容当前工作台表结构 |
| `im_workbench` | `c1c1156` | 更新新测试环境中间件配置,修复 Kafka 发布 |
## 2. 服务边界
### 2.1 im_workbench 负责
| 模块 | 接口范围 |
|---|---|
| 工作台首页 | `GET /v1/workbench` |
| 组织架构 | `/v1/workbench/organization/*` |
| 考勤 | `/v1/workbench/attendance/*` |
| 会议 | `/v1/workbench/meetings*` |
| 会议笔记 | `/v1/workbench/meeting-notes`、`/v1/workbench/meetings/{id}/notes*` |
| 日报 | `/v1/workbench/reports/daily*` |
| 月报 | `/v1/workbench/reports/monthly*` |
| 总经理信箱 | `/v1/workbench/executive-mailbox/*` |
| 工作台业务事件 | 生产 Kafka 事件到 `im.workbench.event` |
### 2.2 im_server 继续负责
| 能力 | 说明 |
|---|---|
| 登录、注册、Token 签发 | C 端登录仍走 `im_server` |
| Redis 登录态写入 | 登录成功后写 `im:session:token:{sha256(token)}` |
| 文件上传 | 暂由 `/v0/file/u/` 处理,工作台只保存 `file_id` |
| WebSocket 实时下发 | 工作台事件由 `im_server` 消费后转 C 端通知 |
| IM 消息、群、好友、在线状态 | 仍全部留在 `im_server` |
## 3. 网关路由
客户端对外仍访问统一域名,由 Nginx/API Gateway 按路径分流:
```text
/v0/channels -> im_server
/v0/file/u/ -> im_server
/v1/im/* -> im_server
/v1/workbench/* -> im_workbench
```
测试环境域名:
| 域名 | 用途 |
|---|---|
| `https://api.118im.com` | 后端 API,包含 `/v1/workbench/*` |
| `https://api-test.118im.com` | 测试 API 备用域名 |
| `https://web.118im.com` | Web 前端同源代理 |
注意:不要再让 `im_server` 代理工作台新接口。新接口应直接进入 `im_workbench`。
## 4. 请求鉴权
工作台接口和 IM 产品 HTTP 保持同一套公共 Header:
| Header | 必填 | 说明 |
|---|---|---|
| `Authorization` | 是 | `Bearer {token}` |
| `X-MeetingIM-APIKey` | 是 | 客户端 API Key |
| `X-Tenant-Code` | 是 | 当前租户编码,例如 `default` |
| `X-IM-Schema` | 是 | 当前固定 `1` |
| `X-Request-ID` | 建议必填 | 请求链路 ID |
| `Idempotency-Key` | 写接口必填 | 写操作幂等键 |
登录态 Redis Key:
```text
im:session:token:{sha256(token)}
```
Redis Value:
```json
{
"user_id": 1572927143048908800,
"tenant_id": 1,
"tenant_code": "default",
"device_id": "ios-device-1",
"auth_level": "auth",
"state": "active",
"issued_at": "2026-09-14T10:00:00Z",
"expires_at": "2026-09-14T12:00:00Z"
}
```
鉴权流程:
1. `im_workbench` 校验 `X-MeetingIM-APIKey` 非空或命中配置白名单。
2. 从 `Authorization` 读取 Bearer Token。
3. 对 Token 做 `sha256`,查 Redis 登录态。
4. 校验 `state=active`、未过期。
5. 校验 Header 的 `X-Tenant-Code` 与登录态 `tenant_code` 一致。
测试环境当前可用 API Key 以部署文档为准,最近验证可用的是新测试环境文档中的 `TINODE_API_KEY`。
## 5. 测试环境配置
配置文件:
```text
/Users/youshunlai/go_workspace/im_workbench/configs/workbench.test.json
```
当前关键配置:
| 配置 | 值 |
|---|---|
| 服务监听 | `:6061` |
| MySQL | `mysql.118im.com:30306` |
| MySQL 业务库 | `tinode` |
| Redis 数据端口 | `redis.118im.com:30637` |
| Redis Sentinel | `redis.118im.com:30638` |
| Kafka Bootstrap | `kafka.118im.com:30835` |
| Kafka 协议 | `PLAINTEXT` |
| Kafka Topic | `im.workbench.event` |
说明:
1. Kafka 测试环境是明文直连,不配置 SASL/TLS。
2. `im.workbench.event` 已在新 Kafka 集群创建。
3. Redis 数据 NodePort 可能落到主节点或副本。服务正常读登录态没问题;如果本地要写临时测试 session,可能遇到 `READONLY`,需要通过真正主库入口或先走真实登录链路。
4. MySQL、Redis 密码不写入本文,按 `im_server/docs/problems/新测试环境部署与中间件连接信息.md` 或部署 Secret 获取。
## 6. 本地启动
本地开发配置:
```bash
IM_WORKBENCH_CONFIG=configs/workbench.local.json go run ./cmd/workbench
```
连接测试环境配置:
```bash
IM_WORKBENCH_CONFIG=configs/workbench.test.json go run ./cmd/workbench
```
如果只做本地接口调试,可以临时打开开发 Header 鉴权:
```bash
IM_WORKBENCH_CONFIG=configs/workbench.test.json \
IM_WORKBENCH_ALLOW_DEV_HEADER_AUTH=true \
go run ./cmd/workbench
```
开发 Header:
```text
X-User-ID: 1572927143048908800
X-Tenant-ID: 1
X-Tenant-Code: default
X-MeetingIM-APIKey: x
X-IM-Schema: 1
X-Request-ID: {uuid}
```
注意:`IM_WORKBENCH_ALLOW_DEV_HEADER_AUTH=true` 只能本地调试使用,测试/生产部署不要开启。
## 7. Kafka 事件
工作台写操作统一投递:
```text
Topic: im.workbench.event
```
事件体:
```json
{
"event_id": "wbe_xxx",
"trace_id": "request-id",
"tenant_id": 1,
"tenant_code": "default",
"actor_user_id": 42,
"module": "meeting",
"action": "meeting.created",
"resource_id": "mtg_xxx",
"target_user_ids": [42, 43],
"title": "会议通知",
"summary": "项目周会",
"occurred_at": "2026-09-14T06:00:00Z",
"data": {}
}
```
当前事件范围:
| 模块 | Action | 触发场景 |
|---|---|---|
| 考勤 | `attendance.record.updated` | 打卡成功 |
| 考勤 | `attendance.appeal.created` | 提交考勤申诉 |
| 会议 | `meeting.created` | 创建会议 |
| 会议 | `meeting.updated` | 修改会议 |
| 会议 | `meeting.canceled` | 取消会议 |
| 会议 | `meeting.response.updated` | 更新参会回执 |
| 会议笔记 | `meeting_note.file.created` | 新增会议笔记文件 |
| 会议笔记 | `meeting_note.file.replaced` | 替换会议笔记文件 |
| 会议笔记 | `meeting_note.file.deleted` | 删除会议笔记文件 |
| 日报 | `daily_report.draft.created` | 创建日报草稿 |
| 日报 | `daily_report.draft.saved` | 保存日报草稿 |
| 日报 | `daily_report.submitted` | 提交日报 |
| 日报 | `daily_report.reminded` | 日报提醒 |
| 月报 | `monthly_report.draft.created` | 创建月报草稿 |
| 月报 | `monthly_report.draft.saved` | 保存月报草稿 |
| 月报 | `monthly_report.submitted` | 提交月报 |
| 月报 | `monthly_report.reopened` | 重开月报 |
| 信箱 | `mailbox.submitted` | 提交总经理信箱 |
已修复问题:`kafka.Writer` 设置了默认 Topic 后,单条 `kafka.Message` 不再重复设置 Topic,否则 `kafka-go` 会报 `Topic must not be specified for both Writer and Message`。
## 8. 数据库现状
当前数据库不迁移,`im_workbench` 仍连接租户库 `tinode`。
主要表:
| 表 | 用途 |
|---|---|
| `im_workbench_apps` | 工作台模块 |
| `im_org_departments` | 组织部门 |
| `im_org_members` | 组织成员 |
| `im_org_visibility_overrides` | 组织可见范围 |
| `im_attendance_rules` | 考勤规则 |
| `im_attendance_shifts` | 考勤班次 |
| `im_attendance_records` | 考勤记录 |
| `im_attendance_checkins` | 打卡流水 |
| `im_attendance_appeals` | 考勤申诉 |
| `im_meetings` | 会议 |
| `im_meeting_participants` | 会议参与人 |
| `im_meeting_note_files` | 会议笔记文件引用 |
| `im_daily_reports` | 日报 |
| `im_monthly_reports` | 月报 |
| `im_mailbox_config` | 总经理信箱配置 |
| `im_mailbox_submissions` | 总经理信箱提交 |
已兼容当前表结构:
| 表 | 当前结构注意点 | 代码处理 |
|---|---|---|
| `im_org_members` | 成员状态字段是 `employment_state` | 查询时返回为 `status` |
| `im_attendance_rules` | 没有 `appeal_deadline` 字段 | 查询返回 `NULL AS appeal_deadline` |
| `im_mailbox_config` | 没有 `version` 字段 | 用 `notice_updated_at` 派生版本 |
服务启动不自动建库建表,不执行 DDL。所有建表、改字段、初始化数据都走人工 SQL 审核和发布。
## 9. 已验证接口
使用新测试环境配置启动本地 `im_workbench`,并开启本地开发 Header 鉴权后,已验证:
| 接口 | 结果 |
|---|---|
| `GET /v1/workbench` | 200 |
| `GET /v1/workbench/organization/departments` | 200 |
| `GET /v1/workbench/attendance/config` | 200 |
| `GET /v1/workbench/executive-mailbox/config` | 200 |
| `POST /v1/workbench/executive-mailbox/submissions` | 200,Kafka 发布成功 |
同时执行:
```bash
go test ./...
```
结果通过。
## 10. 新工作树接手步骤
1. 拉取 `im_workbench` 的 `dev` 分支。
2. 确认包含提交 `c1c1156` 或更新的提交。
3. 查看 `configs/workbench.test.json`,确认中间件地址是新测试环境域名,不是旧 VM `64.118.137.182`。
4. 执行 `go test ./...`。
5. 本地启动:
```bash
IM_WORKBENCH_CONFIG=configs/workbench.test.json \
IM_WORKBENCH_ALLOW_DEV_HEADER_AUTH=true \
go run ./cmd/workbench
```
6. 用开发 Header 调 `GET /v1/workbench`、组织、考勤、信箱配置。
7. 调一个写接口,例如信箱提交,确认返回 200,并在数据库清理测试数据。
8. 关闭开发 Header 鉴权,走真实登录 Token 验证网关链路。
9. 验证公网 `/v1/workbench/*` 路由已经进入 `im_workbench`,并确认网关透传 `Authorization`、`X-MeetingIM-APIKey`、`X-Tenant-Code`、`X-IM-Schema`、`X-Request-ID`。
## 11. 待后续处理
| 事项 | 说明 |
|---|---|
| 真实登录态联调 | 需要通过 `im_server` 登录后生成 Redis session,再从公网 `/v1/workbench/*` 验证 |
| 网关 Header 透传 | 必须确认 `Authorization` 没被 Nginx/API Gateway 清掉 |
| Redis 写入口 | 数据 NodePort 可能落副本,本地造 session 可能遇到 `READONLY` |
| im_server 消费工作台事件 | `im_server` 消费 `im.workbench.event` 后转系统通知/WS 下发需要继续联调 |
| 工作台数据库迁移 | 现阶段不迁,接口稳定后单独做工作台库迁移 |
| 删除 im_server 旧工作台代码 | 等新服务、网关、前端、通知链路全部稳定后再删 |
## 12. 常见问题
### 12.1 `/v1/workbench` 返回 `AUTH_REQUIRED`
优先检查:
1. 是否带 `Authorization: Bearer {token}`。
2. Redis 是否有 `im:session:token:{sha256(token)}`。
3. session 是否 `state=active` 且未过期。
4. `X-Tenant-Code` 是否和 session 中的 `tenant_code` 一致。
5. 网关是否透传 `Authorization`。
6. `im_workbench` 是否连到了和 `im_server` 相同的 Redis。
### 12.2 写接口返回 `workbench event publish failed`
优先检查:
1. Kafka broker 是否为 `kafka.118im.com:30835`。
2. Kafka 是否为 `PLAINTEXT`,不要配置 SASL。
3. Topic `im.workbench.event` 是否存在。
4. 服务代码是否已经包含 Kafka 双 Topic 修复。
### 12.3 组织或考勤接口 500
优先检查当前表结构是否和代码兼容:
1. `im_org_members` 使用 `employment_state`,不是 `status`。
2. `im_attendance_rules` 当前没有 `appeal_deadline`。
3. `im_mailbox_config` 当前没有 `version`。
这些兼容已在当前代码中处理;如果新工作树仍 500,先确认是否拉到最新提交。