coord.md 新增 ARB-019/020/021 三章仲裁章节,修正 ARB-001。 - coord.md: 新增 ARB-019/020/021(student/parent/admin-portal 24 项) - coord.md: 修正 ARB-001(admin P2 预留/schema 文件名/classes 数据源) - 004 §4: 依赖图加 PBFF→DataAna+Msg - 004 §7.2: push-gateway→Redis 软失败标注 - 004 §11.4: 错误码前缀矩阵(11 服务+i18n key) - 004 §11.5: ActionState 信封规范(降级模式方案 B) - matrix §1: 依赖矩阵加 PBFF 边 - matrix §2: 移除 api-gateway 为 iam gRPC 消费方 - matrix §4: admin-portal→teacher-bff - matrix §5: 移除 /sse+鉴权头统一 - matrix §6: 错误码表补 i18n key 列 - 15 个 issue.md: 仲裁结论回写 - push-gateway_contract: 移除 /sse+鉴权头改 X-Internal-Token - packages/contracts: 新建包 ADMIN_* 权限点常量 AI: coord
215 lines
14 KiB
Markdown
215 lines
14 KiB
Markdown
# msg 问题记录
|
||
|
||
> 负责人:ai10
|
||
> 关联:[coord.md](../coord.md)、[contracts/msg_contract.md](../contracts/msg_contract.md)
|
||
> 规则:AI 遇到问题时在此追加条目,coord 仲裁后更新状态
|
||
|
||
---
|
||
|
||
## §0 已有仲裁核查(ai10 复核)
|
||
|
||
> 本节核查 01-understanding.md / 02-architecture-design.md 中引用的已有仲裁,对照源码/proto 验证准确性。
|
||
|
||
### ISSUE-001-ai10:M8 ZodError 已修复 — 核查通过
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:仲裁核查
|
||
- **描述**:01-understanding.md M8 称"GlobalErrorFilter 已识别 ZodError 返回 400"。核查 [global-error.filter.ts](../../../services/msg/src/shared/errors/global-error.filter.ts) L32-42:`else if (exception instanceof ZodError) { statusCode = 400; ... }`,确实已处理,返回 `MSG_VALIDATION_ERROR` + 400。
|
||
- **核查结论**:✅ 仲裁准确,M8 标记"已修复"无误
|
||
- **状态**:已裁决(核查通过,无需处理)
|
||
|
||
### ISSUE-002-ai10:M12 proto 包名规范 — 核查通过
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:仲裁核查
|
||
- **描述**:01-understanding.md M12 称"实际 `next_edu_cloud.msg.v1` 符合规范"。核查 [msg.proto](../../../packages/shared-proto/proto/msg.proto) L3:`package next_edu_cloud.msg.v1;`,与 01-understanding.md 描述一致。
|
||
- **核查结论**:✅ 仲裁准确,但存在规则冲突(见 ISSUE-007)
|
||
- **状态**:已裁决(核查通过)
|
||
|
||
### ISSUE-003-ai10:M2 msg 必须有 Outbox — 核查通过
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:仲裁核查
|
||
- **描述**:01-understanding.md M2 称"004 §7.2 明确 msg 生产 `edu.notification.events`,msg 必须有 Outbox"。核查 004 §7.3 L638 `NotificationRequested` 事件(Msg 投递通知到多渠道)+ known-issues §msg L346"Outbox 强制"。
|
||
- **核查结论**:✅ 仲裁准确,msg 必须实现 Outbox(P5 强制)
|
||
- **状态**:已裁决(核查通过)
|
||
|
||
### ISSUE-004-ai10:core-edu 事件 topic 命名统一 — 核查部分通过
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:仲裁核查
|
||
- **描述**:02-architecture-design.md §7.2 P11 称"coord 已仲裁采用 `edu.teaching.*` 新约定"。核查:
|
||
- 004 §7.2 L623-625 使用 `edu.teaching.assignment.submitted` / `edu.teaching.exam.published` / `edu.teaching.grade.recorded`(新约定)✅
|
||
- [events.proto](../../../packages/shared-proto/proto/events.proto) L9-13 注释仍用 `edu.exam.events` / `edu.homework.events`(旧约定)❌ 未同步
|
||
- [matrix.md](../matrix.md) §4 L112-115 使用 `edu.exam.events` / `edu.homework.events`(旧约定)❌ 未同步
|
||
- **核查结论**:⚠️ 仲裁已作出但未全量同步,events.proto 注释与 matrix.md 仍用旧约定,需 coord 统一更新
|
||
- **状态**:待 coord 同步(见 ISSUE-008)
|
||
|
||
### ISSUE-005-ai10:Push Gateway 调用方向歧义 — 核查通过
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:仲裁核查
|
||
- **描述**:02-architecture-design.md §7.2 P10 称"004 §4.1 写 PushGW→Msg,实际是 Msg→PushGW"。核查 004 §4.1 L413:`push-gateway → Msg | gRPC | 推送通道建立`,方向确实反了。实际流程是 msg 调 push-gateway 的 gRPC PushService.Push(见 [notifications.service.ts](../../../services/msg/src/notifications/notifications.service.ts) L179 fetch POST /internal/push 降级实现)。
|
||
- **核查结论**:✅ 歧义确认,建议 coord 修正 004 §4.1 表述为"Msg → push-gateway (gRPC)"
|
||
- **状态**:待 coord 修正 004
|
||
|
||
---
|
||
|
||
## §1 新发现问题(ai10 提请)
|
||
|
||
### ISSUE-006-ai10:events.proto P9 字段描述不准确
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:契约不明确
|
||
- **描述**:02-architecture-design.md §7.2 P9 称"events.proto ExamEvent / HomeworkEvent / GradeEvent 需补 `class_id` / `student_ids[]` 字段"。核查 events.proto:
|
||
- `ExamEvent` L32 **已有** `class_id` 字段 ✅
|
||
- `HomeworkEvent` L45 **已有** `class_id` 字段 ✅
|
||
- `GradeEvent` L50-59 **无** `class_id`(仅有 `student_id`)❌
|
||
- 三者均**无** `student_ids[]`(复数,用于 fan-out 广播)❌
|
||
- **建议方案**:修正 P9 表述为"`GradeEvent` 需补 `class_id`;全部事件需补 `student_ids[]` 字段(msg fan-out 广播通知需要)"
|
||
- **状态**:待 coord 仲裁
|
||
|
||
### ISSUE-007-ai10:proto 包名规则冲突(project_rules vs 实际)
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:契约不明确
|
||
- **描述**:[project_rules §5](../../../.trae/rules/project_rules.md) 规定"包名规范:`edu.<domain>.v1`(如 `edu.iam.v1`、`edu.core_edu.v1`)",但实际所有 proto 文件使用 `next_edu_cloud.<domain>.v1`(如 msg.proto L3 `next_edu_cloud.msg.v1`、events.proto L3 `next_edu_cloud.events.v1`)。01-understanding.md 称"coord 已裁决采用 `next_edu_cloud.*`",但 project_rules §5 未同步更新,仍写 `edu.<domain>.v1`。
|
||
- **建议方案**:coord 统一裁决,二选一:
|
||
- 方案 A:更新 project_rules §5 为 `next_edu_cloud.<domain>.v1`(与实际 proto 一致)
|
||
- 方案 B:重命名所有 proto package 为 `edu.<domain>.v1`(与规则一致,但改动大)
|
||
- **状态**:待 coord 仲裁
|
||
|
||
### ISSUE-008-ai10:Kafka topic 命名三套约定并存
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:契约不明确
|
||
- **描述**:msg 相关的 Kafka topic 命名存在三套约定:
|
||
- **约定 A(004 §7.2,per-event topic)**:`edu.identity.user.created` / `edu.teaching.exam.published` / `edu.notification.sent`
|
||
- **约定 B(matrix.md §4 + events.proto 注释,aggregate topic)**:`edu.iam.user.events` / `edu.exam.events` / `edu.notification.requested`
|
||
- **约定 C(msg_contract.md §1.4,aggregate topic + action 字段)**:`edu.msg.notification.events`(action: sent/read/recalled/failed)
|
||
- 02-architecture-design.md §5.1/§5.2 采用约定 A;msg_contract.md §1.4 采用约定 C;matrix.md 采用约定 B。known-issues §全局 L182 已标记此冲突。
|
||
- **建议方案**:coord 统一为一套约定。ai10 倾向约定 A(per-event topic),理由:
|
||
- 004 §7.2 已采用,是架构设计意图唯一源
|
||
- per-event topic 便于消费者按需订阅,避免反序列化无关事件
|
||
- 与 NotificationSent / NotificationRead 等事件命名(PascalCase)对齐
|
||
- **状态**:待 coord 仲裁
|
||
|
||
### ISSUE-009-ai10:RPC 数量超预算(17 vs 13)
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:工作量超批
|
||
- **描述**:[ai-allocation.md §3.2](../../ai-allocation.md) L112 与 [matrix.md](../matrix.md) §2 L90 均规定 msg 为"3 Service 13 RPC"。但 02-architecture-design.md §4.2 列出 17 RPC:
|
||
- NotificationService 9 RPC(SendNotification / BatchSendNotification / ListNotifications / GetUnreadCount / MarkAsRead / BatchMarkAsRead / MarkAllAsRead / SearchNotifications / RecallNotification)
|
||
- NotificationPreferenceService 2 RPC(GetPreferences / UpdatePreferences)
|
||
- NotificationTemplateService 6 RPC(CreateTemplate / GetTemplate / ListTemplates / UpdateTemplate / DeleteTemplate / RenderTemplate)
|
||
- 而 msg_contract.md §1.1 列出 13 RPC(分布不同:5+4+4),两文档互相不一致
|
||
- **建议方案**:coord 裁决 RPC 范围,二选一:
|
||
- 方案 A:维持 13 RPC 预算,02-architecture-design.md 裁剪至 13(移除 BatchSendNotification / GetUnreadCount / BatchMarkAsRead / MarkAllAsRead / UpdateTemplate / DeleteTemplate,降级为 REST only 或合并)
|
||
- 方案 B:放宽至 17 RPC,同步更新 ai-allocation.md + matrix.md + msg_contract.md
|
||
- **状态**:待 coord 仲裁
|
||
|
||
### ISSUE-010-ai10:markAsRead 权限点与设计不一致
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:契约不明确
|
||
- **描述**:[notifications.controller.ts](../../../services/msg/src/notifications/notifications.controller.ts) L74 markAsRead 使用 `MSG_NOTIFICATION_MANAGE` 权限,但 02-architecture-design.md §6.1 L730 规定 markAsRead 应使用 `MSG_NOTIFICATION_READ`。MANAGE 权限通常给管理员,学生标记自己通知已读不应需要 MANAGE 权限。
|
||
- **建议方案**:以 02-architecture-design.md §6.1 为准(READ),P5 实现时修正 controller 权限点
|
||
- **状态**:待 coord 确认
|
||
|
||
### ISSUE-011-ai10:DB→ES 降级方向与 ai-allocation §5 相反
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:契约不明确
|
||
- **描述**:
|
||
- [ai-allocation.md §5](../../ai-allocation.md) ai10 设计重点要求"ES 降级查询策略(**DB 不可用时走 ES 索引**)"——即 DB 故障时 ES 作为读模型兜底
|
||
- 02-architecture-design.md §3.2.2 / §3.4 描述"**ES 不可用时降级到 MySQL LIKE 查询**"——即 ES 故障时 DB 兜底
|
||
- 01-understanding.md M16 称"无 DB→ES 降级读路径"
|
||
- 三处描述方向相反,需统一
|
||
- **建议方案**:ai10 倾向双向降级(两种故障场景都覆盖):
|
||
- ES 故障 → DB LIKE 查询(设计文档已覆盖)
|
||
- DB 故障 → ES 只读模式(ai-allocation 要求,设计文档需补充)
|
||
- 但 DB 故障时写操作无法降级(必须等 DB 恢复),仅读操作可走 ES
|
||
- **状态**:待 coord 仲裁
|
||
|
||
### ISSUE-012-ai10:设计文档缺 DLQ 与三层幂等防线
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:前置依赖缺失
|
||
- **描述**:[known-issues §msg](../../../docs/troubleshooting/known-issues.md) L344 / L356 已记录两项 ai10 设计点,但 02-architecture-design.md 未覆盖:
|
||
- **三层幂等防线**(L344):L1 Redis SETNX / L2 msg_idempotency 表 / L3 notifications.source_event_id 唯一索引。设计文档 §5.5 仅描述两层(Redis + DB UNIQUE),缺中间层 msg_idempotency 表
|
||
- **死信队列**(L356):消费失败超 3 次投递 `edu.notification.dlq`。设计文档 §5 完全未提及 DLQ 设计
|
||
- **建议方案**:02-architecture-design.md 补充:
|
||
- §3.1 补 `msg_idempotency` 表 schema(中间层)
|
||
- §5.5 改为三层幂等防线
|
||
- §5 补 DLQ 设计(重试 3 次后投递 `edu.notification.dlq` + 告警)
|
||
- **状态**:待 coord 确认(非阻塞,ai10 自行补充设计文档即可)
|
||
|
||
### ISSUE-013-ai10:events.proto 缺 4 类 message 阻塞 msg 消费
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:前置依赖缺失
|
||
- **描述**:[events.proto](../../../packages/shared-proto/proto/events.proto) 仅有 ClassEvent / ExamEvent / HomeworkEvent / GradeEvent 4 个 message。msg 消费还需要:
|
||
- `UserEvent`(iam 发布 user.created/updated/deleted/role_changed)— 阻塞欢迎通知/角色变更通知
|
||
- `RoleEvent`(iam 发布 role.created/updated)— 阻塞角色变更通知
|
||
- `MasteryEvent`(data-ana 发布 mastery.updated)— 阻塞学情预警通知
|
||
- `NotificationEvent`(msg 发布 notification.sent/read/recalled/failed)— 阻塞 push-gateway 消费 msg 事件
|
||
- **建议方案**:coord 维护 shared-proto,在 P5 启动前补齐这 4 个 message。msg 在 proto 补齐前用通用 JSON payload 解析(A6 假设)
|
||
- **状态**:待 coord 仲裁(🔴 阻塞 P5 消费链路)
|
||
|
||
### ISSUE-014-ai10:msg_contract.md 与 02-architecture-design.md RPC 清单不一致
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:契约不明确
|
||
- **描述**:两文档 RPC 清单存在差异:
|
||
- msg_contract.md 独有(02 缺):GetPreferenceByChannel、ListPreferences
|
||
- 02-architecture-design.md 独有(contract 缺):BatchSendNotification、GetUnreadCount、BatchMarkAsRead、MarkAllAsRead、UpdateTemplate、DeleteTemplate
|
||
- 即使忽略 ISSUE-009 的数量问题,两文档的 RPC 组合也不同
|
||
- **建议方案**:待 ISSUE-009 仲裁后,统一两文档 RPC 清单
|
||
- **状态**:待 coord 仲裁(依赖 ISSUE-009)
|
||
|
||
### ISSUE-015-ai10:msg_contract.md Kafka 发布事件与设计文档不一致
|
||
|
||
- **提请方**:ai10
|
||
- **日期**:2026-07-10
|
||
- **类型**:契约不明确
|
||
- **描述**:
|
||
- msg_contract.md §1.4:`edu.msg.notification.events` topic,单一 NotificationEvent 含 action 字段
|
||
- 02-architecture-design.md §5.2:4 个 per-event topic(`edu.notification.sent` / `edu.notification.read` / `edu.notification.recalled` / `edu.notification.failed`)
|
||
- matrix.md §4 L118:`edu.notification.requested`(第三种命名)
|
||
- **建议方案**:待 ISSUE-008 仲裁 topic 命名约定后统一
|
||
- **状态**:待 coord 仲裁(依赖 ISSUE-008)
|
||
|
||
---
|
||
|
||
## §2 仲裁结论(2026-07-10 coord)
|
||
|
||
> 详见 [coord.md §10 ARB-008](../coord.md#10-arb-008msg-模块-15-项-issue-仲裁)
|
||
|
||
| ISSUE | 仲裁结论 | 执行方 |
|
||
| ------- | ------------------------------------------------------------------------------------------------------------- | ------------ |
|
||
| 001~005 | ✅ 核查通过(001/002/003);004 待 coord 同步 events.proto(ARB-006);005 待 coord 修正 004 §4.1 PushGW 方向 | coord |
|
||
| 006 | ✅ coord 补全 GradeEvent class_id + 全部事件 student_ids[](ARB-011) | coord |
|
||
| 007 | ✅ 统一 `next_edu_cloud.<domain>.v1`(ARB-011) | coord |
|
||
| 008 | ✅ msg 采用具体动作 topic(ARB-013) | coord |
|
||
| 009 | ✅ 维持 13 RPC,裁剪 4 RPC 降级 REST | ai10 |
|
||
| 010 | ✅ markAsRead 权限改为 `MSG_NOTIFICATION_READ` | ai10 |
|
||
| 011 | ✅ 双向降级(ES 故障→DB LIKE;DB 故障→ES 只读) | ai10 |
|
||
| 012 | ✅ 非阻塞,ai10 补 DLQ + 三层幂等设计文档 | ai10 |
|
||
| 013 | ✅ coord 补全 events.proto(ARB-011:NotificationEvent + MasteryEvent) | coord |
|
||
| 014 | ✅ 统一 13 RPC,两文档对齐 | ai10 |
|
||
| 015 | ✅ 统一 topic 命名(ARB-013) | ai10 + coord |
|