Files
Edu/services/data-ana/docs/01-understanding.md
SpecialX faaaf29f67 docs: ai 协作文档体系重构与多 ai 仲裁结果落地
1.AI 协作文档体系重构(objections/worklines/contracts+matrix.md)

2.coord 仲裁文档(final-decisions/cross-review/final-rulings/orchestration)

3.各服务 01/02 文档补全

4.共享包初始化(shared-ts/shared-go/hooks/ui-components/ui-tokens)

5.Proto 契约补全

6.004 架构影响地图更新

7.端口分配表

8.设计规格文档
2026-07-10 12:58:22 +08:00

233 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 模块理解确认书 — data-ana
> AI 标识ai11v2 由 ai11 审核 ai06 v1 后修订)
> 负责模块data-anaP4
> 语言Python 3.12+ / FastAPI 0.115+
> 阶段:架构设计外包 · 阶段 1全局理解v2 审核版
> 日期2026-07-09v1 by ai06/ 2026-07-10v2 审核修订 by ai11
> 关联文档:[ai-allocation.md](../../../docs/architecture/ai-allocation.md)、[004 架构影响地图](../../../docs/architecture/004_architecture_impact_map.md)、[pending-features.md](../../../docs/architecture/roadmap/pending-features.md)、[known-issues.md](../../../docs/troubleshooting/known-issues.md)
> 审核修订说明ai-allocation.md §3.2 将 data-ana 重新分配给 ai11ai 单独分配给 ai12ai11 接手后对 ai06 v1 进行审核,本版为 v2 修订。
---
## 阶段 1 必读清单完成确认
按 ai-allocation.md §4ai11 必读 7 份全局文档 + 全部 `.proto` + `services/data-ana/` 骨架源码:
| # | 文档 | 状态 |
| --- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| 1 | [README.md](../../../README.md) | ✅ 已读 |
| 2 | [MIGRATION_GUIDE.md](../../../MIGRATION_GUIDE.md) | ✅ 已读 |
| 3 | [004 架构影响地图](../../../docs/architecture/004_architecture_impact_map.md) | ✅ 已读v2 重点核对 §1.2/§4.2/§7.2/§11.5/§12.2/§15.3 已仲裁项) |
| 4 | [pending-features.md](../../../docs/architecture/roadmap/pending-features.md) | ✅ 已读 |
| 5 | [project_rules.md](../../../.trae/rules/project_rules.md) | ✅ 已读workspace 规则) |
| 6 | [coding-standards.md](../../../docs/standards/coding-standards.md) | ✅ 已读(重点 §4 Python 规范) |
| 7 | [multi-ai-collaboration.md](../../../docs/standards/multi-ai-collaboration.md) | ✅ 已读 |
| 8 | `packages/shared-proto/proto/*.proto`8 份,重点 analytics.proto + events.proto | ✅ 已读 |
| 9 | `services/data-ana/src/` 全部源码main/config/cdc_consumer/clickhouse_client | ✅ 已读 |
> ai11 不需要读 classes 黄金模板ai-allocation.md §4 矩阵 ai11 列对黄金模板行为 "—"),但审计表横切关注点对齐仍参考 classes 标准。
---
## 1. 我在架构中的位置
- **层级**业务微服务层L5**D6 智能洞察领域**004 §1.1b
- **上游**
- api-gateway 直接 HTTP 代理 `/api/v1/analytics/*` → data-ana:3006见 [api-gateway main.go:142-148](../../api-gateway/main.go)
- teacher-bff / student-bff / parent-bff 聚合查询004 §4.1 + §4.2BFF → 业务服务 gRPC**P4 启用 gRPC**
- ai 服务通过 gRPC 反查学情数据004 §4.1AI → DataAna gRPCAI 出题编排时调 `GetStudentWeakness` / `GetLearningTrend`
- **下游**
- ClickHouse独占读模型宽表 `student_dashboard_view` / `student_errors` / `mastery_snapshot` / `ai_usage_log`
- RedisDataScope 缓存 5min + 预警去重位图 + CDC 幂等去重 SETNX004 §6.3 缓存策略矩阵)
- Kafka消费 Debezium CDC 事件 + 发布 `edu.insight.mastery.updated` 派生数据事件)
- iam gRPC`GetEffectiveDataScope` 解析数据范围,已仲裁 P4 补全,见 004 §15.3 #5
- **通信方式**
- 入口HTTP`/analytics/*`,保留作 Gateway 直连降级)+ **gRPC** `AnalyticsService`P4 启用主入口BFF 调用)
- 出口Kafka 消费CDC 主通道 + 领域事件订阅备通道Kafka 发布(`edu.insight.mastery.updated`**未实现**,属派生数据豁免 Outbox见 004 §12.2
- **端口**HTTP=3006见 [data-ana config.py:7](../src/data_ana/config.py) + [api-gateway config.go:55](../../api-gateway/internal/config/config.go)**gRPC=50055**004 §1.2 服务清单 + §4.2 gRPC 启用阶段矩阵P4 启用)
## 2. 我的限界上下文
- **聚合职责**:学情分析读模型构建 + 查询服务,承载 **D6 智能洞察领域**的"分析/诊断"子域
- **聚合根 / 实体**视图型聚合根ClickHouse 物化):
- `StudentDashboard`学生学情宽表视图ClickHouse 物化)
- `StudentErrorBook`学生错题本ClickHouse 物化)
- `ClassPerformance`班级成绩聚合ClickHouse 即时聚合,不物化)
- `MasterySnapshot`(知识点掌握度快照,**待实现**,含历史版本支持趋势查询)
- `AiUsageLog`AI 用量记录,消费 ai 服务 `edu.insight.ai.usage` 事件落库,供计费/分析用)
- `AttendanceLog`(出勤日志宽表,消费 core-edu CDC `core_edu_attendance`**待实现**,对应 ai-allocation §5 五张宽表之一)
- **业务领域**D6 智能洞察(与 ai 服务共享领域ai 偏"生成"data-ana 偏"分析"
- **我不负责**
- 不负责写模型(成绩由 core-edu 写 MySQLdata-ana 只消费 CDC
- 不负责题库内容(→ content 服务,但消费 content 知识点变更事件用于掌握度维度同步,见 §7
- 不负责通知投递(→ msg 服务消费 data-ana 发布的 `mastery.updated` 事件触发预警)
- 不负责 AI 推理(→ ai 服务ai 通过 gRPC 反向查询 data-ana 学情数据)
- 不负责双轨读的"实时查主库"侧BFF 层负责双轨读data-ana 仅是"聚合查宽表"侧,见 pending-features P4 交付物)
- **数据自治**:独占 `edu_analytics` ClickHouse 数据库(不与 MySQL 写模型混用);可选 Redis与全局共享实例键名加 `data_ana:` 前缀)
## 3. 我与外部的契约
### 消费的 proto message
> **双通道说明**:当前实现走 Debezium CDC直接监听 MySQL binlog不消费 events.proto 领域事件。这是 ADR-008 的设计决策。下表"领域事件"为**未来双消费备通道**(待 P4 后期评估是否启用CDC 才是当前主通道。
| 来源 | message | 通道状态 | 用途 |
| --------------- | --------------------------------------------------------------------------------------------- | ---------------------------------- | ------------------------------------------------- |
| events.proto | `GradeEvent` | 备通道(未消费) | 未来双消费core-edu 成绩写入事件 → 更新学情宽表 |
| events.proto | `ExamEvent` | 备通道(未消费) | 未来双消费:考试事件 → 缓存 exam_id→class_id 映射 |
| events.proto | `HomeworkEvent` | 备通道(未消费) | 未来双消费:作业提交/批改事件 → 更新学情 |
| events.proto | `ClassEvent` | 备通道(未消费) | 未来双消费:班级变更事件 → 同步班级维度 |
| analytics.proto | `GetClassPerformanceRequest` 等 | 自身暴露契约(待实现 gRPC server | P4 启用 gRPC=50055 后暴露 `AnalyticsService` |
| iam.proto | `GetEffectiveDataScopeRequest`**待 coord 在 iam.proto 新增**004 §15.3 #5 已裁决 P4 补全) | 调用契约 | gRPC 调 iam 解析 DataScope结果 Redis 缓存 5min |
### 暴露的 API / 事件
**HTTP 端点**(当前实现,见 [main.py](../src/data_ana/main.py);保留作 Gateway 直连降级):
| method | path | 说明 |
| ------ | ------------------------------------------- | --------------------------------------------- |
| GET | `/healthz` | liveness |
| GET | `/readyz` | readiness含 ClickHouse + CDC + Redis 状态) |
| GET | `/metrics` | Prometheus 指标 |
| GET | `/analytics/class/{class_id}/performance` | 班级成绩分析(平均分/及格率/参考人数) |
| GET | `/analytics/student/{student_id}/weakness` | 学生薄弱知识点mastery < 0.6 |
| GET | `/analytics/student/{student_id}/errorbook` | 学生错题本 |
> **响应信封约束**:以上 HTTP 端点当前实现为 `{success, data, degraded}` 结构,违反 004 §11.5 统一响应信封 ActionStatePython 服务必须改 ActionStatedegraded 作为 `details.degraded` 子字段)。阶段 2 设计已对齐(见 02-architecture-design.md §4.3)。
**gRPC 契约**analytics.protoP4 启用 server端口 50055
- `GetClassPerformance(GetClassPerformanceRequest) → ClassPerformance`
- `GetStudentWeakness(GetStudentWeaknessRequest) → StudentWeakness`
- `GetLearningTrend(GetLearningTrendRequest) → LearningTrend`**当前 HTTP 未暴露**
> **proto 扩展提案**(待 coord 在 shared-proto 新增,见 02-architecture-design.md §4.4
>
> - `GetTeacherDashboard` / `GetStudentDashboard` / `GetParentDashboard` / `GetSchoolDashboard`:四端 Dashboard 聚合ai-allocation §5 要求)
> - `GetClassWarningList` / `GetStudentWarningList`:预警查询
> - `GetMasteryDistribution`:掌握度分布
> - `stream SubscribeMasteryUpdate`实时掌握度推送P5+ 演进,供 BFF SSE 透传)
**发布的领域事件**
| 事件 | Topic004 §7.2 | 触发时机 | 消费者004 §7.3 | Outbox 合规性 |
| ---------------- | ----------------------------- | -------------- | --------------------------------------- | ----------------------------------------------------------- |
| `MasteryUpdated` | `edu.insight.mastery.updated` | 掌握度计算完成 | core-edu推荐个性化练习、msg预警 | **豁免 Outbox**(派生数据,见 004 §12.2 + §15.3 #6 已仲裁) |
> **当前未实现发布**data-ana 当前只消费不发布。掌握度计算完成后通过 `aiokafka.AIOKafkaProducer` 直接发布(已豁免 Outbox004 §15.3 #6 仲裁结论),下游 core-edu / msg 消费。失败重试 3 次仍失败落 `mastery_publish_failed` 本地表。
- **错误码前缀**`DATA_ANA_*`004 §11.4 错误码前缀矩阵已登记,清单见阶段 2 §6.2
- **缓存**RedisDataScope 缓存 5min 事件驱动失效 / CDC event_id 幂等去重 SETNX TTL 7d / 预警去重位图);学情宽表走 ClickHouse 实时CDC 同步延迟 < 5s
## 4. 我的技术栈
- 语言Python 3.12+
- 框架FastAPI 0.115+ / uvicorn
- ORM / 客户端:
- `clickhouse-connect`HTTP 协议,非原生协议)
- `redis-py[asyncio]`**待引入**DataScope 缓存 + 幂等去重 + 预警位图)
- `grpc.aio` + `betterproto`**待引入**P4 启用 gRPC server + 调 iam gRPC
- 消息:`aiokafka`CDC 消费者 AIOKafkaConsumer + 掌握度发布 AIOKafkaProducer
- 配置:`pydantic-settings` BaseSettingsenv_prefix="",全大写环境变量)
- 可观测:
- 日志:`structlog` 24.x`make_filtering_bound_logger`**注意**:旧版 `make_filtering_logger` 已废弃;生产改 JSONRenderer
- 指标:`prometheus-client` + `make_asgi_app()` 挂载 `/metrics`
- 链路:`opentelemetry-sdk` + `OTLPSpanExporter` + `FastAPIInstrumentor.instrument_app(app)` + `grpc.aio` server interceptor待引入
- 序列化JSONDebezium 事件 `schemas.enable=false`,直接 `json.loads`+ protobufgRPC
- 测试pytest + pytest-asyncio + TestcontainersClickHouse + Kafka + Redis 真实依赖,**当前 0% 覆盖率,目标 ≥ 80%**
- 容器Dockerfile 多阶段builder 用 `uv sync --frozen`runtime 用 `python:3.12-slim` 拷贝 `.venv`**当前单阶段待改造**
## 5. 我的阶段归属
- **P4 内容分析阶段M11-M13**:建 DataAna 服务 + CDC 链路落地
- **退出标准**pending-features P4学生查看学情诊断 ClickHouse 宽表 5s 内返回 + CDC 链路延迟 < 5s
- **交付物**pending-features P4DataAna 学情诊断宽表 5s 内返回 + CDC 链路延迟 < 5s + **双轨读策略落地(实时查主库 + 聚合查宽表)** + CDC 模式回写黄金模板 README + 打 tag `v0.4.0-p4`
- **依赖上游**
- P1 地基api-gateway 路由 + arch.db 扫描器 Python 支持
- P2 身份iam `GetEffectiveDataScope` gRPC已仲裁 P4 补全,见 004 §15.3 #5
- P3 核心教学core-edu 写成绩到 MySQLDebezium 监听 binlog+ Outbox 领域事件(备通道)
- P4 同期content 服务(提供知识点 ID 供掌握度计算content → data-ana 事件流见 004 §4 服务依赖图)
- **下游依赖我**
- P5 ai 服务通过 gRPC 查询学情数据004 §4.1AI → DataAna gRPC+ 投递 `edu.insight.ai.usage` 用量事件
- P5 msg 服务消费 `mastery.updated` 触发预警
- **未来阶段演进铺垫**(长远性):
- P5消费 `edu.insight.ai.usage` 落 ai_usage_loggRPC `SubscribeMasteryUpdate` stream RPC 供 BFF SSE 透传
- P6CDC 消费者水平扩展(多实例 + 分区重平衡 + ExamCache Redis 化ClickHouse 容量规划 + TTL数据治理GDPR 删除权Service Mesh mTLS
## 6. 我需要对齐的黄金模板项(对照 classes 服务 + Python 规范)
> Python 服务无 NestJS 装饰器体系,权限校验等通过等价方式实现。
- [ ] 权限装饰器等价物:**当前 HTTP 端点全部裸露,无权限校验**。Gateway 层做 JWT 校验,但 data-ana 本身未校验 `x-user-id` / DataScope。**阶段 2 需设计 FastAPI Depends 权限依赖 + DataScope 过滤注入**
- [ ] 错误码前缀统一:**当前无错误码体系**,降级时返回 `degraded: true` 标记但无业务错误码。**阶段 2 需定义 `DATA_ANA_*` 错误码清单**004 §11.4 已登记前缀)
- [ ] **响应信封对齐 ActionState**004 §11.5 已仲裁 P0 整改):当前 `{success, data, degraded}` 偏离结构,须改为 `{success: true, data: T}` / `{success: false, error: {code, message, details?, traceId?}}`degraded 作为 `details.degraded` 子字段
- [x] logger / metrics / tracer 三支柱(已具备,见 main.py + clickhouse_client.py生产改 JSONRenderer
- [x] `/healthz` + `/readyz` 健康检查已具备readyz 含 ClickHouse ping + CDC 状态;**待补 Redis + iam gRPC 连通性检查**
- [ ] 优雅关闭 SIGTERM当前 lifespan 仅关闭 CDC task + ClickHouse client**未注册 SIGTERM 信号处理器**显式 drain。阶段 2 设计顺序HTTP stop → gRPC graceful stop 30s → CDC commit offset → Kafka producer flush → ClickHouse close → iam channel close
- [ ] 测试覆盖率 ≥ 80%**当前 0%**,无 tests/ 目录。阶段 2 设计测试策略pytest 单元 + pytest-asyncio + TestcontainersClickHouse + Kafka + Redis
- [ ] Dockerfile 多阶段构建:**当前单阶段**`FROM python:3.12-slim``uv sync``COPY src`),非多阶段
- [ ] Pydantic 输入验证:**当前端点直接接收 path param无 Pydantic 请求模型校验**(应补 `ClassPerformanceResponse` 等 response_model
- [x] 配置通过 pydantic-settings 管理(已具备;**待补 Redis / gRPC / 限流 / 降级开关 / feature flags 配置项**,见阶段 2 §6.9
- [x] 异步优先async defaiokafka async consumer
- [ ] 类型注解强制:**部分函数缺返回值标注**(如 `init_logger` 返回 `BoundLogger``_logger` 全局变量标注 `None`,需统一)
- [ ] ruff check 零错误:需阶段 2 验证
- [ ] **CDC 幂等性加强**:当前依赖 ReplacingMergeTree查询未加 `FINAL` / `argMax`,可能读到重复版本(阶段 2 §3.1 修复)
- [ ] **CDC 水平扩展**:当前 ExamCache 为内存缓存,多实例部署不同步,阶段 2 §5.3 设计 Redis 化方案
- [ ] **数据治理**长远性GDPR 删除权在 ClickHouse 的实现mutations 或分区删除)、脱敏字段、审计日志(阶段 2 §10
---
## 服务审计表 — ai11data-anav2 修订)
> 对照 ai-allocation.md §10 审计模板。data-ana 为 Python/FastAPI黄金模板对齐按 Python 规范coding-standards §4评估。
> 符号说明:✅ 已实现 | ❌ 缺失 | ⚠️ 部分实现
| 服务 | 权限校验 | 错误码前缀 | 响应信封 | logger | metrics | tracer | /healthz | /readyz | 优雅关闭 | 测试覆盖率 | Dockerfile | Redis | gRPC server |
| -------- | -------- | ---------- | ---------------------- | ------------ | ------------- | ------- | -------- | ----------------------------- | ------------------- | ---------- | ---------- | ----- | --------------------- |
| data-ana | ❌ | ❌ | ❌(偏离 ActionState | ✅ structlog | ✅ prometheus | ✅ OTel | ✅ | ⚠️(含 CH+CDC缺 Redis/iam | ⚠️ 仅 lifespan 关闭 | 0% | ❌ 单阶段 | ❌ | ❌P4 待启用 50055 |
### 审计发现的关键差距按优先级v2 修订)
1. **P0 权限校验缺失**:所有 `/analytics/*` 端点裸露,无 DataScope 过滤。学生 A 可查询学生 B 的错题本(越权风险)。阶段 2 必须设计 `Depends(require_permission)` + `Depends(inject_data_scope)` 依赖注入
2. **P0 响应信封偏离 ActionState**004 §11.5 已仲裁 P0 整改v2 新增):当前 `{success, data, degraded}` 必须改为 ActionStatedegraded 作为 `details.degraded` 子字段
3. **P0 gRPC server 未实现**004 §4.2 P4 启用analytics.proto 定义了 `AnalyticsService` 但 data-ana 当前仅 HTTP。阶段 2 需引入 `grpc.aio` + `betterproto` 实现 gRPC server端口 50055
4. **P1 事件发布缺失**`edu.insight.mastery.updated` 事件未发布(已豁免 Outbox004 §15.3 #6 仲裁),下游 core-edu/msg 无法消费。需设计掌握度计算 + Kafka producer 直接发布链路
5. **P1 ClickHouse schema 不规范**:当前 `student_dashboard_view` 实为 MergeTree 表,应为 ReplacingMergeTree(last_updated);查询未加 FINAL/argMax 可能读重复版本。无 DDL 文件管理。阶段 2 需产出完整 ClickHouse DDL5 张宽表:考试/作业/成绩/掌握度/出勤,对应 ai-allocation §5 要求)
6. **P1 掌握度计算算法缺失**:当前 `_handle_grades_event``score / 100.0` 简化,未实现 pending-features 要求的"加权滑动平均 + 遗忘曲线"。阶段 2 §9 给出具体公式
7. **P1 Dashboard API 不完整**ai-allocation §5 要求):当前仅 3 个查询端点,缺教师/学生/家长/校管理 4 端 Dashboard 聚合 API
8. **P1 预警阈值设计缺失**ai-allocation §5 要求):未设计预警阈值配置 API 与触发逻辑
9. **P2 测试覆盖率 0%**:无 tests/ 目录pytest 未配置
10. **P2 Dockerfile 单阶段**未做多阶段构建builder + runtime镜像体积大
11. **P2 无 Pydantic 响应模型**:端点返回 `dict` 而非 `BaseModel`,无 `response_model` 校验
12. **P2 CDC 水平扩展缺失**ExamCache 内存缓存多实例不同步;缺消费者 group_id / 分区重平衡设计
13. **P2 缓存策略缺失**:未引入 Redis缺 DataScope 缓存 / CDC 幂等去重 / 预警位图
14. **P2 content 服务交互缺失**004 §4 服务依赖图显示 content → data-ana 事件流,当前未消费 content 知识点变更事件
15. **P2 数据治理缺失**长远性GDPR 删除权、脱敏、审计日志未设计
16. **P2 ClickHouse 容量规划缺失**5 张宽表年增量估算 + TTL + 冷热分层未设计
---
## coord 交叉审查结论对齐v2 修订,原 v1 标题"待 coord 交叉审查的跨模块契约对齐项"
> v1 提请的 5 项跨模块契约对齐项coord 已在 [coord-cross-review.md](../../../docs/architecture/coord-cross-review.md) 完成仲裁,裁决结论中涉及架构设计意图的部分已沉淀到 004 对应章节004 §15.3 共性问题 #1-#7。本节 v2 改为"对齐状态"。
| # | 议题v1 提请) | coord 裁决结论004 §15.3 | data-ana 文档对齐状态v2 |
| --- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| 1 | **data-ana 是否发布 `edu.insight.mastery.updated` 事件** | §15.3 #6:派生数据事件豁免 Outbox允许直接 Kafka producer | ✅ v2 已对齐§3 标注"豁免 Outbox",阶段 2 §5.2 设计直接 producer 链路 |
| 2 | **data-ana / ai 是否需要实现 gRPC server** | §4.2 gRPC 启用阶段矩阵P4 content + data-ana 启用 | ✅ v2 已对齐§1 标注"gRPC=50055 P4 启用",阶段 2 §1 分层图含 grpc.aio Server |
| 3 | **CDC 直连 vs Outbox 领域事件双通道** | §15.3 #6 + ADR-008维持 CDC 为主通道events.proto 作为业务语义补充,待 P4 后期评估是否双消费 | ✅ v2 已对齐§3 双通道说明 + 标注"领域事件为备通道" |
| 4 | **data-ana DataScope 过滤实现位置** | §15.3 #5iam 新增 `GetEffectiveDataScope` gRPC RPCP4 补全data-ana 在 ClickHouse 查询 SQL 拼接时注入 WHERE | ✅ v2 已对齐§3 列出 iam.proto 调用契约;阶段 2 §6.1 设计 `inject_data_scope` Depends |
| 5 | **data-ana ClickHouse DDL 管理位置** | §15.3 #7:采纳 `infra/clickhouse/ddl/`coord 建立data-ana 提供 DDL 内容 | ✅ v2 已对齐:阶段 2 §3 标注"DDL 文件由 coord 统一管理在 `infra/clickhouse/ddl/`" |
| 6 | **新增 `edu.insight.ai.usage` topic**v1 阶段 2 §8.3 #3 提请) | §15.3 #4:补登,见 004 §7.2 | ✅ v2 已对齐:阶段 2 §5.1 列出消费此 topic |
| 7 | **iam GetEffectiveDataScope proto 新增**v1 阶段 2 §8.3 #2 提请) | §15.3 #5P4 补全 | ✅ v2 已对齐§3 列出 iam.proto 调用契约 |
> v1 §8.3 "未决设计决策"3 项全部已被 coord 仲裁v2 不再列为"未决"。文档后续修订如发现新冲突,按 ai-allocation.md §9.4 proto 变更流程提请 coord。
---
**AI Agent**: ai11 (data-ana) — v2 审核修订自 ai06 v1
**Branch**: 单仓库并行模式(直接提交 main
**Coordinator**: coord-ai
**v1 作者**: ai06原同时负责 data-ana + aiai-allocation §3.2 v2 重新分配后 data-ana → ai11 / ai → ai12