Files
Edu/services/content
SpecialX 61d824924a fix: 修复集成测试中发现的全部 bug — 15 服务端到端验证通过
修复涵盖 6 大类问题:

1. api-gateway
   - 路径前缀剥离 /api 而非 /api/v1,保留下游 /v1/ controller 前缀
   - JWKS URL 默认值修复
   - publicPaths 白名单对齐 /v1/iam/*

2. iam
   - iam.module.ts exports 补充 PermissionCacheService 和 IamRepository
   - main.ts resolveProtoPath() 多路径探测 proto 文件

3. core-edu
   - app.module.ts AuthMiddleware 全局注册

4. BFF 层 GraphQL 端点(teacher-bff / parent-bff / student-bff)
   - teacher-bff: mock dataScope OWN→SELF 对齐 GraphQL enum;WHATWG Request header .get() 提取
   - parent-bff: handleNodeRequestAndResponse 不存在 → 直接 yoga(req,res);WHATWG Request header .get() 提取
   - student-bff: auth.resolver 移除 ActionState 信封返回扁平对象;WHATWG Request header .get() 提取

5. ai
   - Kafka 事务降级 + 10s 超时
   - gRPC 拦截器降级
   - dev mode 禁用事务模式

6. 前端 + 共享包
   - teacher-portal: MF 插件条件实例化 + transpilePackages + extensionAlias
   - ui-components: error-boundary.tsx 添加 use client
   - ui-tokens: tailwind-theme.css 移除 @layer base
   - shared-ts: 导出从源码改为 dist 编译产物;OutboxModule global:true

7. infra
   - .gitignore 补充 keys/ *.pem *.key secrets/ 排除规则
   - infra/init-sql/02-all-services-schema.sql 36 张表 DDL

验证结果:
- TS typecheck: 19 个 workspace 项目全部通过
- Go vet + Ruff: 通过
- 15 服务全部启动成功
- 3 个 BFF GraphQL 端点 + 4 个前端页面全部 200
- Gateway → iam → core-edu 端到端链路验证通过

AI identity: trae-main(集成测试修复会话)
2026-07-11 01:41:46 +08:00
..
2026-07-10 18:57:57 +08:00
2026-07-10 18:57:57 +08:00
2026-07-10 18:57:57 +08:00
2026-07-10 18:57:57 +08:00

content 内容资源服务

版本1.0P4 完整实现) 端口HTTP 3005 / gRPC 50054

职责

内容资源限界上下文,管理 Textbook、Chapter、KnowledgePoint、Question 四个聚合。 支持多存储MySQL写模型权威源+ Neo4j知识图谱派生读模型+ ElasticsearchP5 引入,题库全文检索)。 事件驱动Outbox 模式发布 4 个聚合 topicNeo4j Sync Worker 异步消费事件同步图谱。

技术栈

  • NestJS 10.x + TypeScript 5.6ESM相对 import 带 .js 后缀)
  • Drizzle ORM 0.31MySQLgetDb() 函数式懒加载)
  • neo4j-driver 5.x知识图谱仅读模型查询
  • KafkaJS 2.2idempotent producer + transactionalId
  • @grpc/grpc-js + @nestjs/microservicesgRPC server 50054
  • @paralleldrive/cuid2统一 ID 策略)
  • Zod 3.xController 层全量 schema.parse
  • pino日志+ prom-client指标+ OpenTelemetry追踪

开发

pnpm install
pnpm dev        # HTTP 3005 + gRPC 50054
pnpm build
pnpm typecheck
pnpm lint
pnpm test

环境变量

变量 说明
PORT HTTP 服务端口(默认 3005
GRPC_PORT gRPC 服务端口(默认 50054
DATABASE_URL MySQL 连接串(必填)
KAFKA_BROKERS Kafka broker 列表(逗号分隔,默认 localhost:9092
NEO4J_URL Neo4j Bolt 连接 URL可选
NEO4J_PASSWORD Neo4j 密码(可选)
REDIS_URL Redis 连接预留P5+ 缓存)
ES_URL Elasticsearch 地址P5 引入)
JWT_SECRET JWT 密钥Gateway 校验,服务可选)
OTEL_EXPORTER_OTLP_ENDPOINT OpenTelemetry OTLP 端点(可选)

模块结构

src/
├─ config/              # env / database(getDb) / kafka / neo4j
├─ grpc/                # gRPC controllers4 Service, 22 RPC
│  ├─ grpc.module.ts
│  ├─ grpc-types.ts     # 手动定义 proto message TS 类型
│  ├─ textbook.grpc.controller.ts
│  ├─ chapter.grpc.controller.ts
│  ├─ knowledge-graph.grpc.controller.ts
│  └─ question.grpc.controller.ts
├─ textbooks/           # 教材领域schema/repository/service/controller/dto
├─ chapters/            # 章节领域
├─ knowledge-points/    # 知识点领域(含前置依赖管理)
├─ questions/           # 题库领域
├─ shared/
│  ├─ errors/           # ApplicationError + GlobalErrorFilterCONTENT_* 前缀 + ZodError 分支)
│  ├─ health/           # /healthz + /readyzDB/Neo4j/Kafka 多依赖检查)
│  ├─ lifecycle/        # 优雅关闭
│  ├─ observability/    # logger / metrics / tracer
│  ├─ outbox/           # Outbox 模式schema/repository/publisher/service/module/events
│  └─ sync/             # Neo4j Sync Worker消费 Kafka 事件异步同步图谱)
├─ middleware/          # auth.middleware + permission.guard
├─ app.module.ts
└─ main.ts              # HTTP + gRPC hybrid app

REST API 端点

Textbooks

方法 路径 说明
POST /textbooks 创建教材
GET /textbooks 教材列表(支持分页/过滤)
GET /textbooks/:id 教材详情
PUT /textbooks/:id 更新教材
DELETE /textbooks/:id 删除教材

Chapters

方法 路径 说明
POST /chapters 创建章节
GET /chapters/textbook/:textbookId 按教材列出章节
GET /chapters/:id 章节详情
PUT /chapters/:id 更新章节
DELETE /chapters/:id 删除章节

Knowledge Points

方法 路径 说明
POST /knowledge-points 创建知识点
GET /knowledge-points/chapter/:chapterId 按章节列出知识点
GET /knowledge-points/:id 知识点详情
GET /knowledge-points/:id/prerequisites 查询前置依赖(读 Neo4j
POST /knowledge-points/:id/prerequisites 添加前置依赖(发 Outbox 事件)
DELETE /knowledge-points/:id/prerequisites/:prerequisiteId 移除前置依赖(发 Outbox 事件)
PUT /knowledge-points/:id 更新知识点
DELETE /knowledge-points/:id 删除知识点

Questions

方法 路径 说明
POST /questions 创建题目
GET /questions 题目列表(支持分页/过滤)
GET /questions/knowledge-point/:knowledgePointId 按知识点列出题目
GET /questions/:id 题目详情
PUT /questions/:id 更新题目
DELETE /questions/:id 删除题目

gRPC API端口 50054

Proto 定义:packages/shared-proto/proto/content.proto(包名 next_edu_cloud.content.v1

Service RPC 数 关键方法
TextbookService 5 CreateTextbook / GetTextbook / ListTextbooks / UpdateTextbook / DeleteTextbook
ChapterService 5 CreateChapter / GetChapter / ListChapters / UpdateChapter / DeleteChapter
KnowledgeGraphService 4 GetPrerequisites / GetLearningPath / AddPrerequisite / RemovePrerequisite
QuestionService 8 CreateQuestion / BatchCreateQuestions / GetQuestion / ListQuestions / UpdateQuestion / DeleteQuestion / PublishQuestion / SearchQuestions

合计 22 RPC。

事件驱动

Outbox 模式

业务操作create/update/delete在同一事务内写业务表 + content_outbox_events 表。 独立 OutboxPublisher worker 轮询 pending 记录投递 Kafkaat-least-once最大重试 5 次,指数退避)。

Kafka Topics4 个聚合 topicaction 字段区分事件类型)

Topic 事件类型action
edu.content.textbook.events created / updated / published / archived
edu.content.chapter.events created / updated / deleted
edu.content.knowledge_point.events created / updated / prerequisite_added / prerequisite_removed
edu.content.question.events created / updated / published / deleted

Neo4j Sync Worker

消费 edu.content.knowledge_point.events topic异步同步知识图谱

  • kp.created / kp.updated → MERGE 节点
  • prerequisite_added → MERGE 关系
  • prerequisite_removed → DELETE 关系

Neo4j 不可用时非阻塞跳过(不影响 MySQL 写入和主流程)。

健康检查

端点 用途 鉴权
GET /healthz 存活探针liveness仅返回进程状态
GET /readyz 就绪探针readiness检查 DB/Neo4j/Kafka失败返回 503

质量校验

检查项 命令 状态
类型检查 pnpm typecheck 0 错误
Lint pnpm lint 0 错误
单元测试 pnpm test 182 tests 通过
覆盖率 vitest run --coverage 66.94%≥60%

对外契约

  • gRPC protopackages/shared-proto/proto/content.proto
  • 事件 protopackages/shared-proto/proto/events.protoTextbookEvent / ChapterEvent / KnowledgePointEvent / QuestionEvent
  • 契约文档:docs/architecture/issues/contracts/content_contract.md