Merge worktree branch merge-15-modules-to-main-5ug5xJ

This commit is contained in:
SpecialX
2026-07-10 15:28:20 +08:00
parent 60d7173545
commit df62ffc176
51 changed files with 11559 additions and 1908 deletions

View File

@@ -7,6 +7,7 @@
> 日期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 修订。
> v2.1 审核修订ai11核查发现多处 004 章节引用断裂§4.2/§11.4/§11.5/§15.3 在 004 正文中不存在coord-cross-review §6 整改清单要求 coord 补充但尚未落实),已改为引用 coord-cross-review.md 对应裁决;修正 topic 命名统一为 `edu.insight.mastery.updated`;补充 events.proto AIUsageEvent 缺失说明。
---
@@ -41,11 +42,11 @@
- 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
- iam gRPC`GetEffectiveDataScope` 解析数据范围,已仲裁 P4 补全,见 [coord-cross-review.md §2](../../docs/architecture/coord-cross-review.md) #3
- **通信方式**
- 入口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 启用)
- 出口Kafka 消费CDC 主通道 + 领域事件订阅备通道Kafka 发布(`edu.insight.mastery.updated`**未实现**,属派生数据豁免 Outbox [coord-cross-review.md §3.3](../../docs/architecture/coord-cross-review.md) + 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**[coord-cross-review.md §4.3](../../docs/architecture/coord-cross-review.md) 全局端口矩阵 + [matrix.md §2](../../docs/architecture/issues/matrix.md)P4 启用)
## 2. 我的限界上下文
@@ -79,7 +80,7 @@
| 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 |
| iam.proto | `GetEffectiveDataScopeRequest`**待 coord 在 iam.proto 新增**[coord-cross-review.md §2](../../docs/architecture/coord-cross-review.md) #3 已裁决 P4 补全;当前 iam.proto 仅有 4 RPC无此 RPC**P4 阻塞项** | 调用契约 | gRPC 调 iam 解析 DataScope结果 Redis 缓存 5min |
### 暴露的 API / 事件
@@ -94,7 +95,7 @@
| 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)。
> **响应信封约束**:以上 HTTP 端点当前实现为 `{success, data, degraded}` 结构,违反统一响应信封 ActionState[coord-cross-review.md §5.3](../../docs/architecture/coord-cross-review.md) 已裁决 Python 服务必须改 ActionStatedegraded 作为 `details.degraded` 子字段)。阶段 2 设计已对齐(见 02-architecture-design.md §4.3)。
**gRPC 契约**analytics.protoP4 启用 server端口 50055
@@ -113,11 +114,13 @@
| 事件 | Topic004 §7.2 | 触发时机 | 消费者004 §7.3 | Outbox 合规性 |
| ---------------- | ----------------------------- | -------------- | --------------------------------------- | ----------------------------------------------------------- |
| `MasteryUpdated` | `edu.insight.mastery.updated` | 掌握度计算完成 | core-edu推荐个性化练习、msg预警 | **豁免 Outbox**(派生数据,见 004 §12.2 + §15.3 #6 已仲裁 |
| `MasteryUpdated` | `edu.insight.mastery.updated` | 掌握度计算完成 | core-edu推荐个性化练习、msg预警 | **豁免 Outbox**(派生数据,见 [coord-cross-review.md §3.3](../../docs/architecture/coord-cross-review.md) + 004 §12.2 |
> **当前未实现发布**data-ana 当前只消费不发布。掌握度计算完成后通过 `aiokafka.AIOKafkaProducer` 直接发布(已豁免 Outbox004 §15.3 #6 仲裁结论),下游 core-edu / msg 消费。失败重试 3 次仍失败落 `mastery_publish_failed` 本地表。
> **当前未实现发布**data-ana 当前只消费不发布。掌握度计算完成后通过 `aiokafka.AIOKafkaProducer` 直接发布(已豁免 Outboxcoord-cross-review.md §3.3 仲裁结论),下游 core-edu / msg 消费。失败重试 3 次仍失败落 `mastery_publish_failed` 本地表。
- **错误码前缀**`DATA_ANA_*`004 §11.4 错误码前缀矩阵已登记,清单见阶段 2 §6.2
> **Topic 命名一致性**:本模块统一使用 `edu.insight.mastery.updated`(与 004 §7.2 + matrix.md §4 对齐。contract.md 早期版本写 `edu.data_ana.mastery.events`,已在 v2.1 修正。
- **错误码前缀**`DATA_ANA_*`[matrix.md §6](../../docs/architecture/issues/matrix.md) 错误码前缀矩阵已登记,清单见阶段 2 §6.2
- **缓存**RedisDataScope 缓存 5min 事件驱动失效 / CDC event_id 幂等去重 SETNX TTL 7d / 预警去重位图);学情宽表走 ClickHouse 实时CDC 同步延迟 < 5s
## 4. 我的技术栈
@@ -145,7 +148,7 @@
- **交付物**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
- P2 身份iam `GetEffectiveDataScope` gRPC已仲裁 P4 补全,见 [coord-cross-review.md §2](../../docs/architecture/coord-cross-review.md) #3**当前 iam.proto 未实现P4 阻塞项**
- P3 核心教学core-edu 写成绩到 MySQLDebezium 监听 binlog+ Outbox 领域事件(备通道)
- P4 同期content 服务(提供知识点 ID 供掌握度计算content → data-ana 事件流见 004 §4 服务依赖图)
- **下游依赖我**
@@ -160,8 +163,8 @@
> 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` 子字段
- [ ] 错误码前缀统一:**当前无错误码体系**,降级时返回 `degraded: true` 标记但无业务错误码。**阶段 2 需定义 `DATA_ANA_*` 错误码清单**[matrix.md §6](../../docs/architecture/issues/matrix.md) 已登记前缀)
- [ ] **响应信封对齐 ActionState**[coord-cross-review.md §5.3](../../docs/architecture/coord-cross-review.md) 已裁决 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
@@ -210,17 +213,17 @@
## 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 提请的 5 项跨模块契约对齐项coord 已在 [coord-cross-review.md](../../../docs/architecture/coord-cross-review.md) 完成仲裁。本节 v2.1 改为"对齐状态",并标注落实情况
| # | 议题v1 提请) | coord 裁决结论(004 §15.3 | data-ana 文档对齐状态v2 |
| # | 议题v1 提请) | coord 裁决结论(coord-cross-review.md | data-ana 文档对齐状态v2.1 |
| --- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| 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 调用契约 |
| 1 | **data-ana 是否发布 `edu.insight.mastery.updated` 事件** | §3.3:派生数据事件豁免 Outbox允许直接 Kafka producer | ✅ v2 已对齐§3 标注"豁免 Outbox",阶段 2 §5.2 设计直接 producer 链路 |
| 2 | **data-ana / ai 是否需要实现 gRPC server** | §2.1P4 content + data-ana 启用 gRPC | ✅ v2 已对齐§1 标注"gRPC=50055 P4 启用",阶段 2 §1 分层图含 grpc.aio Server |
| 3 | **CDC 直连 vs Outbox 领域事件双通道** | §3.3 + ADR-008维持 CDC 为主通道events.proto 作为业务语义补充,待 P4 后期评估是否双消费 | ✅ v2 已对齐§3 双通道说明 + 标注"领域事件为备通道" |
| 4 | **data-ana DataScope 过滤实现位置** | §2 #3iam 新增 `GetEffectiveDataScope` gRPC RPCP4 补全data-ana 在 ClickHouse 查询 SQL 拼接时注入 WHERE | ✅ v2 已对齐§3 列出 iam.proto 调用契约;阶段 2 §6.1 设计 `inject_data_scope` Depends |
| 5 | **data-ana ClickHouse DDL 管理位置** | §4:采纳 `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 提请) | §3.2:补登,见 004 §7.2**events.proto AIUsageEvent message 待 coord 补充** | ✅ v2 已对齐:阶段 2 §5.1 列出消费此 topic;⚠️ events.proto 缺 AIUsageEvent 定义 |
| 7 | **iam GetEffectiveDataScope proto 新增**v1 阶段 2 §8.3 #2 提请) | §2 #3P4 补全**当前 iam.proto 仅 4 RPC未实现P4 阻塞项** | ✅ v2 已对齐§3 列出 iam.proto 调用契约;⚠️ iam.proto 未实现 |
> v1 §8.3 "未决设计决策"3 项全部已被 coord 仲裁v2 不再列为"未决"。文档后续修订如发现新冲突,按 ai-allocation.md §9.4 proto 变更流程提请 coord。

View File

@@ -16,11 +16,11 @@
1. **契约先行**proto 已定义analytics.proto / events.proto / iam.proto实现前不修改 proto如需修改走 coord 流程ai-allocation.md §9.4
2. **CQRS 读写分离**data-ana 是纯读模型服务(无 MySQL 写ClickHouse 宽表由 CDC 投影构建
3. **事件驱动**data-ana 消费 CDC主通道+ 领域事件(备通道,待 P4 后期评估);发布 `edu.insight.mastery.updated` 派生数据事件(豁免 Outbox004 §12.2 + §15.3 #6 已仲裁)
4. **gRPC 优先**004 §4.1 + §4.2 明确 BFF → 业务服务走 gRPC**P4 启用 data-ana gRPC server 端口 50055**HTTP 保留作 Gateway 直连降级)
5. **DataScope 过滤**004 §5.3 DataScope 6 级在查询层注入 WHEREiam `GetEffectiveDataScope` gRPC004 §15.3 #5 已仲裁 P4 补全)
3. **事件驱动**data-ana 消费 CDC主通道+ 领域事件(备通道,待 P4 后期评估);发布 `edu.insight.mastery.updated` 派生数据事件(豁免 Outbox[coord-cross-review.md §3.3](../../docs/architecture/coord-cross-review.md) + 004 §12.2 已仲裁)
4. **gRPC 优先**004 §4.1 + [coord-cross-review.md §2.1](../../docs/architecture/coord-cross-review.md) 明确 BFF → 业务服务走 gRPC**P4 启用 data-ana gRPC server 端口 50055**HTTP 保留作 Gateway 直连降级)
5. **DataScope 过滤**004 §5.3 DataScope 6 级在查询层注入 WHEREiam `GetEffectiveDataScope` gRPC[coord-cross-review.md §2](../../docs/architecture/coord-cross-review.md) #3 已仲裁 P4 补全)
6. **三支柱可观测**structlog + prometheus-client + OpenTelemetry已具备需补业务指标 + gRPC server interceptor
7. **统一响应信封 ActionState**004 §11.5 已仲裁 P0 整改):成功 `{success: true, data: T}` / 失败 `{success: false, error: {code, message, details?, traceId?}}` / 降级 `degraded` 作为 `details.degraded` 子字段
7. **统一响应信封 ActionState**[coord-cross-review.md §5.3](../../docs/architecture/coord-cross-review.md) 已裁决 P0 整改):成功 `{success: true, data: T}` / 失败 `{success: false, error: {code, message, details?, traceId?}}` / 降级 `degraded` 作为顶层 `details.degraded` 子字段(非 `error.details`
8. **降级模式**外部依赖ClickHouse / Kafka / iam gRPC / Redis不可用时返回骨架数据 + `details.degraded: true`
9. **Python 规范**pydantic-settings 配置 / Pydantic 模型校验 / async 优先 / 类型注解强制 / ruff 零错误
10. **长远架构演进**:为 P5ai 用量消费 / gRPC stream、P6CDC 水平扩展 / 容量规划 / 数据治理 / Service Mesh做好铺垫见 §14 / §19
@@ -295,13 +295,15 @@ ORDER BY (student_id, class_id, attendance_date);
| `GetAdminDashboard` | `GetAdminDashboardRequest{user_id, scope, scope_id?}` | `AdminDashboard` | `ANALYTICS_ADMIN_DASHBOARD` |
| `GetWarnings` | `GetWarningsRequest{class_id?, severity?, since?}` | `WarningList` | `ANALYTICS_WARNING_READ` |
| `GetMasteryDistribution` | `GetMasteryDistributionRequest{class_id, subject_id, knowledge_point_id?}` | `MasteryDistribution` | `ANALYTICS_CLASS_READ` |
| `GetStudentMastery` | `GetStudentMasteryRequest{student_id, subject_id?}` | `StudentMastery` | `ANALYTICS_STUDENT_READ` |
| `TriggerWarning` | `TriggerWarningRequest{target_id, warning_type, severity}` | `TriggerWarningResponse` | `ANALYTICS_WARNING_READ` |
| `SubscribeMasteryUpdate` | `SubscribeMasteryUpdateRequest{student_id?, class_id?}` | `stream MasteryUpdateEvent` | `ANALYTICS_STUDENT_READ` |
> **proto 扩展提案**(待 coord 审议):上述新增 RPC 的 message 定义需在 `packages/shared-proto/proto/analytics.proto` 补充。`SubscribeMasteryUpdate` 为 server-streaming RPC为 P5+ AI 个性化推荐预留实时推送通道。
> **proto 扩展提案**(待 coord 审议):上述新增 RPC 的 message 定义需在 `packages/shared-proto/proto/analytics.proto` 补充,共 12 RPC3 现有 + 9 扩展)。`SubscribeMasteryUpdate` 为 server-streaming RPC为 P5+ AI 个性化推荐预留实时推送通道。
**权限校验**gRPC server interceptor 从 metadata 提取 `x-user-id` / `x-user-roles` / `x-data-scope`,调用 `AuthDepends` 等价逻辑。
### 4.3 ActionState 统一响应信封(004 §11.5 P0 整改)
### 4.3 ActionState 统一响应信封(coord-cross-review.md §5.3 P0 整改)
所有 HTTP/gRPC 响应必须遵循 ActionState 信封:
@@ -318,23 +320,22 @@ class ActionStateError(BaseModel):
trace_id: str | None = None
class ActionState(BaseModel, Generic[T]):
"""统一响应信封(004 §11.5.
"""统一响应信封(coord-cross-review.md §5.3 裁决.
成功:{success: true, data: T}
失败:{success: false, error: {code, message, details?, trace_id?}}
降级success=true 但 error.details.degraded=true保留功能但数据可能不完整
降级:{success: true, data: T, details: {degraded: true}}(保留功能但数据可能不完整)
"""
success: bool
data: T | None = None
error: ActionStateError | None = None
details: dict[str, Any] | None = None # 降级标记放此字段,不放 error
@classmethod
def ok(cls, data: T, *, degraded: bool = False) -> "ActionState[T]":
# 降级不是错误success=Truedegraded 标记放 details 子字段(非 error.details
details = {"degraded": True} if degraded else None
# 简化degraded 作为 data 的元信息附加,复杂场景用 details
return cls(success=True, data=data, error=None if not degraded else
ActionStateError(code="DATA_ANA_DEGRADED", message="degraded mode",
details=details))
return cls(success=True, data=data, error=None, details=details)
@classmethod
def fail(cls, code: str, message: str, *, trace_id: str | None = None,
@@ -361,7 +362,7 @@ class StudentScore(BaseModel):
# 端点返回类型ActionState[ClassPerformanceData]
```
> **P0 整改要点**:当前 main.py 返回 `{success, data, degraded}` 三字段平铺,违反 004 §11.5。实现阶段需重构为 `ActionState[T]` 泛型,`degraded` 移到 `error.details.degraded`。
> **P0 整改要点**:当前 main.py 返回 `{success, data, degraded}` 三字段平铺,违反 coord-cross-review.md §5.3 裁决。实现阶段需重构为 `ActionState[T]` 泛型,`degraded` 移到顶层 `details.degraded`(非 `error.details`,降级不是错误)
## 5. 事件设计
@@ -547,13 +548,13 @@ async def readyz() -> dict:
| 被调用 | api-gateway | HTTP | `/analytics/*` | Gateway 代理(降级通道) |
| 被调用 | teacher-bff / student-bff / parent-bff | gRPC | `AnalyticsService.*` | BFF 聚合查询4 端 Dashboard |
| 被调用 | aiP5+ | gRPC | `AnalyticsService.GetStudentWeakness / GetLearningTrend / SubscribeMasteryUpdate` | AI 个性化出题上下文 + 实时掌握度推送 |
| 调用 | iam | gRPC | `IamService.GetEffectiveDataScope`004 §15.3 #5 已仲裁 P4 补全 | DataScope 解析 |
| 调用 | iam | gRPC | `IamService.GetEffectiveDataScope`[coord-cross-review.md §2](../../docs/architecture/coord-cross-review.md) #3 已仲裁 P4 补全**当前 iam.proto 未实现** | DataScope 解析 |
| 消费 | core-eduCDC | Kafka | `edu-cdc.next_edu_cloud.core_edu_grades/exams/homework_submissions/attendance` | 学情 + 考勤数据投递 |
| 消费 | core-eduCDC | Kafka | `edu-cdc.next_edu_cloud.classes` | 班级维度同步 |
| 消费 | iamCDC | Kafka | `edu-cdc.next_edu_cloud.iam_users` | 用户 dataScope 同步 |
| 消费 | contentCDC | Kafka | `edu-cdc.next_edu_cloud.content_knowledge_points` | 知识点元数据同步v2 新增) |
| 消费 | aiP5+ | Kafka | `edu.insight.ai.usage`004 §15.3 #6 已仲裁004 §7.2 已登记) | AI 用量落库 |
| 发布 | core-edu / msg | Kafka | `edu.insight.mastery.updated`004 §12.2 + §15.3 #6 已仲裁:派生数据豁免 Outbox | 掌握度更新通知 |
| 消费 | aiP5+ | Kafka | `edu.insight.ai.usage`[coord-cross-review.md §3.2](../../docs/architecture/coord-cross-review.md) 已仲裁004 §7.2 已登记) | AI 用量落库 |
| 发布 | core-edu / msg | Kafka | `edu.insight.mastery.updated`[coord-cross-review.md §3.3](../../docs/architecture/coord-cross-review.md) + 004 §12.2 已仲裁:派生数据豁免 Outbox | 掌握度更新通知 |
| 发布 | msg / core-edu | Kafka | `edu.insight.warning.triggered`v2 新增,需 coord 在 004 §7.2 登记) | 预警触发通知 |
> **004 §4.1 服务间通信矩阵对齐**content → data-ana 已声明"教学内容变更通知",本次落实为 CDC 订阅 `content_knowledge_points` 表。
@@ -562,10 +563,10 @@ async def readyz() -> dict:
### 8.1 假设
- **假设 1**iam 在 P4 阶段提供 `GetEffectiveDataScope(userId) → DataScope` gRPC API004 §15.3 #5 已仲裁)。若 iam 未及时提供fallback 为:从 `x-user-roles` 头推导admin=ALL, teacher=CLASS_TAUGHT, student=SELF但无法支持细粒度年级/学校范围
- **假设 1**iam 在 P4 阶段提供 `GetEffectiveDataScope(userId) → DataScope` gRPC API[coord-cross-review.md §2](../../docs/architecture/coord-cross-review.md) #3 已仲裁)。**当前 iam.proto 仅 4 RPC 未实现此 RPCP4 阻塞项**。若 iam 未及时提供fallback 为:从 `x-user-roles` 头推导admin=ALL, teacher=CLASS_TAUGHT, student=SELF但无法支持细粒度年级/学校范围
- **假设 2**core-edu 的 `core_edu_homework_submissions` / `core_edu_attendance` 表存在 binlog。若不存在需 core-edu 补表或走 Outbox 事件(领域事件备通道)
- **假设 3**ClickHouse `ReplacingMergeTree` 在查询时需 `FINAL` 关键字确保去重生效。**v2 修复要求**:所有查询加 `FINAL` 或使用 `argMax` 聚合(当前实现未加,是 P0 整改项)
- **假设 4**coord 已在 004 §7.2 登记新增 `edu.insight.ai.usage` topic004 §15.3 #6 已仲裁)
- **假设 4**coord 已在 004 §7.2 登记新增 `edu.insight.ai.usage` topic[coord-cross-review.md §3.2](../../docs/architecture/coord-cross-review.md) 已仲裁);**events.proto AIUsageEvent message 待 coord 补充**
### 8.2 技术风险
@@ -582,22 +583,22 @@ async def readyz() -> dict:
| 大数据量 Dashboard 聚合超时 | 管理员 Dashboard 全校聚合慢 | 物化视图预聚合 + 异步刷新 + 缓存 5min |
| 知识点元数据与成绩关联失败 | mastery_snapshot 缺知识点标题 | content CDC 同步 + 缺失时显示 `knowledge_point_id` |
### 8.3 coord 交叉审查结论对齐v2原"未决设计决策"已全部仲裁)
### 8.3 coord 交叉审查结论对齐v2.1:原"未决设计决策"已全部仲裁)
| # | 议题 | coord 仲裁结论 | 涉及文档 |
| --- | ------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | ----------------------- |
| 1 | data-ana 发布 `edu.insight.mastery.updated` 用直接 producer非 Outbox是否合规 | ✅ 已仲裁:派生数据事件豁免 Outbox004 §12.2 + §15.3 #6 | 004 §12.2 |
| 2 | 新增 `edu.insight.ai.usage` topic + `AIUsageEvent` proto message | ✅ 已仲裁coord 在 004 §7.2 登记 + events.proto 补 message | 004 §7.2 + events.proto |
| 3 | iam 新增 `GetEffectiveDataScope` gRPC RPC | ✅ 已仲裁P4 补全(004 §15.3 #5 | iam.proto |
| 4 | data-ana 实现 gRPC server 决策 | ✅ 已仲裁P4 启用(004 §4.2 gRPC 启用阶段矩阵) | 004 §4.2 |
| 1 | data-ana 发布 `edu.insight.mastery.updated` 用直接 producer非 Outbox是否合规 | ✅ 已仲裁:派生数据事件豁免 Outbox[coord-cross-review §3.3](../../docs/architecture/coord-cross-review.md) + 004 §12.2 | 004 §12.2 |
| 2 | 新增 `edu.insight.ai.usage` topic + `AIUsageEvent` proto message | ✅ 已仲裁coord 在 004 §7.2 登记 + events.proto 补 message**⚠️ events.proto 当前缺 AIUsageEvent待 coord 落实** | 004 §7.2 + events.proto |
| 3 | iam 新增 `GetEffectiveDataScope` gRPC RPC | ✅ 已仲裁P4 补全([coord-cross-review §2](../../docs/architecture/coord-cross-review.md) #3**⚠️ iam.proto 当前仅 4 RPC未实现** | iam.proto |
| 4 | data-ana 实现 gRPC server 决策 | ✅ 已仲裁P4 启用([coord-cross-review §2.1](../../docs/architecture/coord-cross-review.md) gRPC 启用阶段) | 004 §4.1 |
| 5 | ClickHouse DDL 管理位置(建议 `infra/clickhouse/ddl/` | ⏳ 待 coord 建立 `infra/clickhouse/ddl/` 目录 + data-ana 提供内容 | infra/ |
| 6 | 端口冲突检查data-ana HTTP=3006 / gRPC=50055 | ✅ 无冲突(004 §1.2 端口分配) | 004 §1.2 |
| 7 | 错误码前缀检查:`DATA_ANA_*` | ✅ 无冲突(004 §11.4 错误码前缀矩阵) | 004 §11.4 |
| 8 | 黄金模板对齐Python 服务无 NestJS 装饰器,权限校验用 FastAPI Depends 等价物是否认可 | ✅ 已仲裁:认可(004 §15.3 | — |
| 6 | 端口冲突检查data-ana HTTP=3006 / gRPC=50055 | ✅ 无冲突([coord-cross-review §4.3](../../docs/architecture/coord-cross-review.md) 全局端口矩阵) | port-allocation |
| 7 | 错误码前缀检查:`DATA_ANA_*` | ✅ 无冲突([matrix.md §6](../../docs/architecture/issues/matrix.md) 错误码前缀矩阵) | matrix.md §6 |
| 8 | 黄金模板对齐Python 服务无 NestJS 装饰器,权限校验用 FastAPI Depends 等价物是否认可 | ✅ 已仲裁:认可([coord-cross-review §5.3](../../docs/architecture/coord-cross-review.md) | — |
| 9 | `edu.insight.warning.triggered` topic 新增 | ⏳ 待 coord 在 004 §7.2 登记v2 新提案) | 004 §7.2 |
| 10 | analytics.proto 扩展4 端 Dashboard / Warning / MasteryDistribution / Stream RPC | ⏳ 待 coord 审议v2 新提案§4.2 | analytics.proto |
> 所有"未决设计决策"已消除,进入实现阶段无阻塞。剩余 3 项 ⏳ 为 v2 新提案,待 coord 审议但不阻塞 P4 主体实现(可先用现有 RPC + HTTP 端点兜底)。
> 所有"未决设计决策"已消除。**P4 阻塞项**#2 events.proto 缺 AIUsageEvent、#3 iam.proto 缺 GetEffectiveDataScope均待 coord 落实。剩余 3 项 ⏳ 为 v2 新提案,待 coord 审议但不阻塞 P4 主体实现(可先用现有 RPC + HTTP 端点 + mock 兜底)。
---
@@ -783,7 +784,7 @@ ENV PATH="/app/.venv/bin:$PATH"
ENV PYTHONUNBUFFERED=1
EXPOSE 3006 50055
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -f http://localhost:3006/healthz || exit 1
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:3006/healthz')" || exit 1
CMD ["python", "-m", "uvicorn", "src.data_ana.main:app", \
"--host", "0.0.0.0", "--port", "3006"]
```
@@ -945,12 +946,26 @@ CDC → ClickHouse 原始表 → MaterializedView → 宽表(自动聚合)
- **AI 驱动的学情诊断**data-ana 提供数据ai 服务提供模型,组合成"智能诊断报告"
- **多租户**:当前 school_id 隐含在 class_id 中,远期可显式多租户隔离
## 19. 服务审计表 v2黄金模板对齐
## 19. 非功能性需求NFRv2.1 新增
| 维度 | 指标 | 目标值 | 验证方式 |
| ---------- | ----------------------------- | --------------- | ------------------------------- |
| 性能 | ClickHouse 宽表查询 P99 延迟 | < 5s | P4 退出标准 + Prometheus 监控 |
| 性能 | CDC 链路延迟 | < 5s | Debezium ts_ms → CH 写入时间差 |
| 性能 | gRPC RPC P99 延迟 | < 500ms | OTel trace |
| 可用性 | P4 单实例 | 99% | 降级模式保证 |
| 可用性 | P6 多实例 + ClickHouse 集群 | 99.9% | HPA + 副本 |
| 安全 | DataScope 越权防护 | 0 越权 | 权限测试 + 渗透测试 |
| 安全 | PII 日志脱敏 | 100% student_id hash | structlog processor 单测 |
| 可扩展性 | CDC 消费者水平扩展 | N 实例无重复 | ReplacingMergeTree + Redis SETNX |
| 数据保留 | ClickHouse TTL | 见 §11.1 | TTL 策略自动执行 |
## 20. 服务审计表 v2黄金模板对齐
| 维度 | 状态 | 说明 |
| ------------- | ---- | ----------------------------------------------------------------------- |
| 契约proto | ✅ | analytics.proto 已定义 3 RPCv2 提案扩展 7 RPC |
| 路由 | ✅ | HTTP 13 端点 + gRPC 10 RPC |
| 契约proto | ✅ | analytics.proto 已定义 3 RPCv2 提案扩展至 12 RPC含 GetStudentMastery / TriggerWarning |
| 路由 | ✅ | HTTP 14 端点3 基础 + 11 业务)+ gRPC 12 RPC |
| 数据访问 | ✅ | ClickHouse 5 宽表 + Redis 缓存 + iam gRPC |
| 鉴权 | ✅ | FastAPI Depends 等价物 + 7 权限点 |
| 错误处理 | ✅ | 13 错误码 `DATA_ANA_*` + ActionState 信封 |
@@ -960,6 +975,7 @@ CDC → ClickHouse 原始表 → MaterializedView → 宽表(自动聚合)
| 健康检查 | ✅ | /healthz + /readyzv2 补 redis/iam_grpc |
| 配置管理 | ✅ | pydantic-settings 完整配置项§15 |
| 降级模式 | ✅ | 4 降级场景CH/Kafka/Redis/iam |
| NFR | ✅ | v2.1 新增 §19性能/可用性/安全/可扩展性目标已定义 |
| 响应信封 | ⚠️ | v2 设计对齐 ActionState实现阶段需重构P0 整改) |
| Redis | ⚠️ | v2 设计就绪,实现阶段需新增 redis-py 依赖 + RedisClient |
| gRPC server | ⚠️ | v2 设计就绪,实现阶段需新增 grpc.aio + betterproto + server interceptor |
@@ -975,5 +991,6 @@ CDC → ClickHouse 原始表 → MaterializedView → 宽表(自动聚合)
**AI Agent**: ai11 (data-ana)
**Branch**: 单仓库并行模式(直接提交 main
**Coordinator**: coord-ai
**v2 修订依据**: ai-allocation.md §3.2 重新分配 + 004 §1.2/§4.2/§7.2/§11.5/§12.2/§15.3 + ai-allocation §5 设计重点 + pending-features P4 退出标准
**v2 审核结论**: 16 项遗漏已全部补强3 项 P0 + 5 项 P1 + 8 项 P2文档进入实现阶段无阻塞
**v2 修订依据**: ai-allocation.md §3.2 重新分配 + coord-cross-review.md §2/§3.3/§5.3 + 004 §4.1/§7.2/§12.2 + ai-allocation §5 设计重点 + pending-features P4 退出标准
**v2.1 审核修订**: 修正 004 章节引用断裂§4.2/§11.4/§11.5/§15.3 不存在→改引 coord-cross-review修正 ActionState 实现矛盾degraded 从 error.details 移至顶层 details补 RPC 至 12 个GetStudentMastery/TriggerWarning修正 HTTP 端点计数 14Dockerfile HEALTHCHECK 改用 urllib 避免 curl 依赖;新增 §19 NFR 章节
**v2 审核结论**: 16 项遗漏已全部补强3 项 P0 + 5 项 P1 + 8 项 P2文档进入实现阶段无阻塞P4 阻塞项iam.proto GetEffectiveDataScope + events.proto AIUsageEvent 待 coord 落实,可用 fallback/mock 兜底)