docs: add workbench migration handoff guide
This commit is contained in:
@@ -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,先确认是否拉到最新提交。
|
||||||
Reference in New Issue
Block a user