Files
Edu/services/classes/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

16 KiB
Raw Blame History

模块理解确认书 — classes

AIai07TS / 教学组织 · 黄金模板) 阶段:阶段 1 交付物 日期2026-07-10 关联:004 架构影响地图AI 分配方案pending-features P1项目规则

本确认书定位classes 是 Edu 微服务的 黄金模板ai-allocation.md §3.4),是其余 8 个 TS 服务的对照基准。本确认书既是对 classes 现状的审计,也是为其他 AI 提供的"读这一份即可理解黄金模板全貌"的入口。


1. 我在架构中的位置

  • 层级L5 业务微服务层004 §3.1 六层架构)
  • 业务领域D2 教学组织领域004 §1.1b承载班级Class聚合根
  • 上游(谁调用我)
    • api-gatewayGo/GinHTTP 反向代理 /api/v1/classes/*http://classes:3001/classes/*Gateway 已注册 classes 路由块,含精确路径 + 通配路径)
    • teacher-bffNestJSP2 起通过 GraphQL 聚合调用 classes 班级列表(教师仪表盘)
    • 未来:student-bffparent-bff(同样走 BFF 聚合)
  • 下游(我调用谁)
    • MySQL(独占库 classes_db,连接串 DATABASE_URLmysql2 连接池 + Drizzle ORM
    • Redis(依赖已声明 ioredisenv 已留 REDIS_URL 占位当前未启用P3 合并入 core-edu 后启用班级列表缓存)
    • Kafka(依赖已声明 kafkajs当前未启用P3 起 Outbox 事件发布 edu.org.class.created 等)
  • 通信方式
    • 入口:HTTP/REST(当前实现,端口 3001
    • 出口MySQLDrizzle ORM
    • 演进proto 已定义 ClassService5 个 RPCP3 起 core-edu 合并 classes 后启用 gRPC server 50053
  • 不持有跨服务状态:无本地内存缓存,无 WebSocket 连接

1.1 黄金模板职责

classes 除了承载 D2 教学组织领域(班级 CRUD业务外首要职责是作为黄金模板

黄金模板职责 说明
横切关注点基准 错误处理 / 可观测性 / 安全 / 契约 / 测试 / 文档 / 配置 / Dockerfile 全部落地,其他 TS 服务对齐
目录结构基准 src/{main,app.module,config,middleware,<domain>,shared} 标准结构
对照 checklist 源 产出黄金模板对照 checklist02 架构设计 §10)供 ai01-ai10 自检
模式回写 各阶段新模式实现后回写本模板Outbox 模式 P3 / 长连接 P5 / CDC P4

2. 我的限界上下文

2.1 我负责的聚合 / 实体

聚合根 实体 / 值对象 当前表 职责
Class(班级) name、gradeId、headTeacherId、description classes 班级 CRUD、按年级过滤、班主任归属

演进P3 合并入 core-edu 后classes 表与 subjects(学科)、enrollment(选课)同属 D2 教学组织域,由 core-edu 统一承载(见 004 §1.3 CICD→Edu 映射)。

2.2 业务领域归属

  • D2 教学组织领域004 §1.1bclasses 独占此领域当前P3 起与 subjects、enrollment 共同组成 D2
  • 上游依赖:无业务领域依赖(教学组织是基础数据,不依赖其他业务领域)
  • 下游被依赖:
    • core-edu D3 教学核心域(考试/作业按班级归属)
    • data-ana D6 智能洞察域(班级维度统计聚合)
    • msg D5 沟通通知域(班级群组广播)

2.3 我不负责什么(边界外)

  • 学科subjects→ core-eduP3 新增D2 教学组织)
  • 选课 / 学生分班enrollment→ core-eduP3 新增)
  • 考试 / 作业 / 成绩 → core-eduD3 教学核心)
  • 教材 / 知识点 / 题库 → contentD4 内容资源)
  • 站内信 / 通知投递 → msgD5 沟通通知)
  • 学情分析 / 掌握度计算 → data-anaD6 智能洞察)
  • 用户 / 角色 / 权限管理 → iamD1 身份认证)
  • JWT 校验 → api-gatewayclasses 仅读 x-user-id / x-user-roles 头)
  • 年级grade数据 → 当前 classes 仅持有 gradeId 外键引用,年级实体归属待 core-edu P3 定义(当前由前端/管理端维护)

3. 我与外部的契约

3.1 我消费的 proto message从 shared-proto

  • 当前不消费任何外部 protoclasses 是基础数据源,不反向依赖业务服务)
  • 未来 P3 起core-edu 合并 classes 后,消费 iam.protoBatchGetUsers(班主任信息批量查询)

3.2 我暴露的契约

当前 REST API已实现classes.controller.ts

Method Path 权限 请求体 / 参数 响应 说明
POST /classes CLASSES_CREATE {name, gradeId, ...} {success, data: ClassResponse} 创建班级
GET /classes CLASSES_READ ?gradeId=<uuid>(可选) {success, data: ClassResponse[]} 列表,支持按年级过滤
GET /classes/:id CLASSES_READ path: id {success, data: ClassResponse} 单条查询
PUT /classes/:id CLASSES_UPDATE path:id + {name?, ...} {success, data: ClassResponse} 更新(空 body 抛 ValidationError
DELETE /classes/:id CLASSES_DELETE path: id {success: true} 删除(先校验存在)

响应信封:遵循 ActionState004 §11.5),成功 {success:true, data:T},失败 {success:false, error:{code,message,details?,traceId?}}

健康检查(见 health.controller.ts

Method Path 鉴权 用途
GET /healthz liveness进程存活
GET /readyz readiness校验 DB SELECT 1,失败 503
GET /metrics Prometheus 指标抓取(见 main.ts 第 23-26 行注册)

Proto 契约(见 classes.proto

package next_edu_cloud.classes.v1;
service ClassService {
  rpc CreateClass(CreateClassRequest) returns (Class);
  rpc GetClass(GetClassRequest) returns (Class);
  rpc ListClasses(ListClassesRequest) returns (ListClassesResponse);
  rpc UpdateClass(UpdateClassRequest) returns (Class);
  rpc DeleteClass(DeleteClassRequest) returns (Empty);
}

proto 完备性5 个 RPC 与 REST 端点一一对应,已包含分页字段(page_size / page_tokenREST 实现尚未落地分页。P3 合并后由 core-edu 启用 gRPC server 50053004 §16.7.3 #1

我发布的领域事件当前未实现P3 由 core-edu 接管)

事件 触发时机 Topic遵循 004 §7.2 消费者
ClassCreated 班级创建成功 edu.org.class.created data-ana建班级维度宽表行
ClassUpdated 班级信息变更 edu.org.class.updated data-ana、msg班主任变更通知
ClassDeleted 班级删除 edu.org.class.deleted data-ana、core-edu关联检查
ClassTransferred 班主任变更 edu.org.class.transferred msg通知新/旧班主任、data-ana

事件 message 契约events.proto 已定义 ClassEventevent_id / aggregate_id / event_type / occurred_at / class_id / name / action / metadataevents.proto 第 15-24 行。Topic 命名遵循 004 §7.2 edu.<domain>.<aggregate>.<action> 强制格式。


4. 我的技术栈

维度 选型 说明
语言 TypeScript 5.6+ ESM 模式("type": "module"),相对 import 用 .js 后缀
框架 NestJS 10 装饰器 + DI适合 DDD 分层
ORM Drizzle ORM 0.31 参数化查询,类型安全,替代 TypeORM
数据库 MySQL 8mysql2 驱动) 连接池 connectionLimit: 10
校验 Zod 3.23 输入 DTO 校验controller 层 schema.parse(body)
日志 pino 9 + pino-prettydev 结构化 JSONbase:{service,version}
指标 prom-client 15 自定义 Counter/Histogram + 默认进程指标,/metrics 端点
链路 OpenTelemetry SDK + OTLP exporter auto-instrumentationsserviceName=classes
测试 Vitest 2.1 + @vitest/coverage-v8 单元测试mock repository阈值 60%(待提升至 80%
容器 node:20-alpine多阶段构建 builder + runtime 两阶段(项目规则要求 node:22-alpine待对齐
ID 生成 uuid v4 当前实现project_rules 要求 cuid2黄金模板待迁移
预留依赖 ioredis、kafkajs 已声明但未使用,为 P3 Redis 缓存 + Kafka 事件预留

5. 我的阶段归属

  • 阶段P1 地基阶段(已实现,黄金模板)
  • 当前阶段目标pending-features P1classes 域 CRUD 端到端跑通 + 全横切关注点落地 + 30 分钟可复制新服务
  • 依赖上游阶段产出P1 是地基classes 是最早交付的服务)
  • 未来演进路径
    • P3合并入 core-eduai08 负责classes 表 + subjects + enrollment 共同组成 D2 教学组织域;启用 gRPC server 50053
    • P3补齐 Outbox 事件发布能力(shared/outbox/ 目录)
    • P3启用 Redis 班级列表缓存TTL 5 分钟,事件驱动失效,见 004 §6.3
    • P3落地 DataScope 6 级 WHERE 注入(见 004 §5.3,当前 PermissionGuard 仅做角色级校验)

6. 我需要对齐的黄金模板项(对照 classes 自身——作为基准的自我审计)

classes 是黄金模板本身,本节为自我审计,确认各项已落地,供其他 TS 服务对照。

检查项 状态 证据 待整改
权限装饰器 @RequirePermission permission.guard.ts + controller 全部方法装饰
错误码前缀 CLASSES_ application-error.ts 7 类错误码均带前缀
loggerpino logger.ts
metricsprom-client metrics.ts + /metrics 端点
tracerOTel ⚠️ tracer.ts 第 20 行仍用 console.log,需改 logger.info P1 整改
/healthz health.controller.ts liveness
/readyz readiness 校验 DB SELECT 1,失败 503
优雅关闭SIGTERM main.ts 第 31-34 行 + lifecycle.service.ts
Zod 输入验证 classes.dto.ts + controller schema.parse(body)
GlobalErrorFilter global-error.filter.ts 捕获 ZodError + ApplicationError
Dockerfile 多阶段 Dockerfile builder + runtime 两阶段 node:20→22
测试覆盖率 ⚠️ vitest.config.ts 阈值 60%,需提升至 80% P1 整改
shared/outbox/ 目录 缺失,需补齐事件发布能力 P3 补齐
typeorm 冗余依赖 package.json 第 33 行仍声明 typeorm已用 Drizzle需移除 P1 整改
@Req()@Query() classes.controller.ts 第 49-53 行 list 方法仍用 @Req() P1 整改
ID 生成 cuid2 classes.service.ts 第 1 行用 uuid v4 P3 迁移

整改项汇总4 项 P1 立即整改tracer console.log / 测试覆盖率 / typeorm 移除 / @Req 替换)+ 2 项 P3 演进outbox / cuid2详见 02 架构设计 §11 整改清单


7. 待 coord 仲裁 / 提请事项

# 议题 我的倾向 影响
1 classes 在 P3 合并入 core-edu 后,黄金模板源码是否保留独立目录 services/classes/ 保留作为只读对照基准core-edu 复制其结构) 影响 ai08 合并策略与黄金模板 checklist 归属
2 node:20-alpinenode:22-alpine 升级是否在 P1 立即做? 立即做project_rules §15.8 镜像预拉清单已是 node:22-alpine 影响所有 TS 服务 Dockerfile 基准
3 cuid2 迁移时机P1 黄金模板立即迁移,还是 P3 合并时统一迁移? P1 立即迁移(黄金模板应先行,避免 ai08 继承 uuid 遗留) 影响 classes 表主键、proto message 字段类型