feat(api-gateway): 添加content服务代理路由
main.go添加textbooks/chapters/knowledge-points/questions四组路由 config.go新增ContentServiceURL字段 docs: known-issues记录P4 content端到端验证经验
This commit is contained in:
@@ -230,12 +230,17 @@
|
||||
|
||||
### 2.5 content(TS/NestJS,P4)
|
||||
|
||||
| 场景 | 技术/规则 |
|
||||
| ---------- | ------------------------------------------------------------------ |
|
||||
| 知识图谱 | Neo4j 查询前置依赖图(秒级返回) |
|
||||
| 题库 CRUD | P4 仅 CRUD,P5 引入 ES 实现检索,避免 MySQL FULLTEXT → ES 迁移成本 |
|
||||
| 双写避免 | Neo4j/ES 不直接双写,由消费 Kafka 事件同步,天然最终一致 |
|
||||
| Neo4j 写入 | Content 服务写 MySQL 同时发事件,独立 worker 消费事件同步 Neo4j |
|
||||
| 场景 | 技术/规则 |
|
||||
| -------------- | ------------------------------------------------------------------------------- |
|
||||
| 知识图谱 | Neo4j 查询前置依赖图(秒级返回) |
|
||||
| 题库 CRUD | P4 仅 CRUD,P5 引入 ES 实现检索,避免 MySQL FULLTEXT → ES 迁移成本 |
|
||||
| 双写避免 | Neo4j/ES 不直接双写,由消费 Kafka 事件同步,天然最终一致 |
|
||||
| Neo4j 写入 | Content 服务写 MySQL 同时发事件,独立 worker 消费事件同步 Neo4j |
|
||||
| API 字段名 | 请求体用 TS schema 字段名(如 `order`),非 DB 列名(如 `order_num`) |
|
||||
| Neo4j 不可用 | 未设置 NEO4J_URL 时 driver=null,getNeo4jSession 返回 null,业务正常落库 MySQL |
|
||||
| Neo4j 连接超时 | driver 配置 connectionTimeout:3000,避免 Neo4j 不可用时拖慢 HTTP 响应 |
|
||||
| Drizzle int | drizzle-orm/mysql-core 导出 `int()` 不是 `integer()` |
|
||||
| db 常量导出 | database.ts 导出 `db` 常量替代 `getDb()` 函数,与 core-edu/classes 黄金模板对齐 |
|
||||
|
||||
### 2.6 data-ana(Python/FastAPI,P4)
|
||||
|
||||
@@ -318,6 +323,7 @@
|
||||
|
||||
| 日期 | 时间 | 模块 | 做了什么 + 学到什么 |
|
||||
| ---------- | ---- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 2026-07-09 | 上午 | content/api-gateway | **P4 内容分析服务端到端打通**:(1) content 服务系统性修复:database.ts 导出 db 常量;env.ts JWT_SECRET/ES_URL/NEO4J_URL/NEO4J_PASSWORD 改 optional 加 DEV_MODE;neo4j.ts driver 惰性创建+try/catch+connectionTimeout:3000;health/lifecycle 改用 Drizzle;global-error.filter 移除 @types/express 依赖;textbooks.schema 修复 integer→int + 导出 NewTextbook/NewChapter 类型;textbooks.controller 移除 body as any + 加 PUT/DELETE。(2) 新建 3 模块:chapters(CRUD + 按 textbook 查询)、knowledge-points(CRUD + Neo4j 前置依赖图非阻塞查询)、questions(CRUD + 4 种题型校验)。(3) Gateway 路由扩展:textbooks/chapters/knowledge-points/questions 四组路由。(4) 数据库:content-init.sql 4 张表。(5) E2E 验证:POST /textbooks 201 → POST /chapters 201(字段用 order 非 orderNum)→ POST /knowledge-points 201(Neo4j 不可用 MySQL 正常写入)→ POST /questions 201 → GET 各列表 200。**学到**:Drizzle schema TS 字段名与 DB 列名解耦(order→order_num),API 请求体用 TS 字段名;Neo4j 不可用时必须 driver=null(不设 NEO4J_URL),否则每次请求尝试连接拖慢响应;neo4j-driver safeCreateNode 用 try/catch 非阻塞,MySQL 数据始终先落库。 |
|
||||
| 2026-07-09 | 凌晨 | core-edu/api-gateway | **P3 核心教学服务端到端打通**:(1) core-edu 服务系统性修复 13 项:database.ts 导出 db 常量替代 getDb();env.ts JWT_SECRET 改 optional 加 DEV_MODE;kafka.ts connectKafka 加 try/catch 不阻塞启动;main.ts 去全局 /api 前缀 + connectKafka 改 void 非阻塞;app.module 移除未用 AuthMiddleware/ClassesesModule 加 HealthModule;3 个 controller 路由去前缀去 UseGuards 从 x-user-id 读身份;exams/homework service datetime 列 ISO 字符串转 Date 修复 drizzle toISOString 错误;修正 10 处相对 import 路径;health/lifecycle 改用 Drizzle 原生查询;新增 core-edu-init.sql 4 张表。(2) Gateway 路由扩展:发现 internal/routing/routing.go 是死代码(未被 main 引用),真正路由在 main.go;在 main.go 添加 exams/homework/grades 三组路由(无尾斜杠+通配符);删除 routing.go;config.go 加 CoreEduServiceURL。(3) DEV_MODE 环境变量问题:Go 不自动加载 .env,必须在启动前 export DEV_MODE=true 否则 dev-token 被拒 401。(4) E2E 验证:POST /exams 201 → GET /exams/:id 200 → GET /exams/class/:id 200 → POST /homework 201 → POST /grades 201 → Outbox 3 条事件正确写入(exam.failed 因 Kafka 未启动,homework/grade pending)。**学到**:drizzle datetime 列需 Date 对象不是 ISO 字符串(mapToDriverValue 调 toISOString);Go 项目 .env 不会自动加载需显式 export 或 godotenv 库;NestJS controller 路由前缀与 Gateway 代理路径要协调(Gateway 去掉 /api/v1 后转发,controller 用裸路径如 'exams');Outbox 模式业务事务同写验证通过,Kafka 未启动时事件 status=failed 但业务数据已落库。 |
|
||||
| 2026-07-09 | 上午 | iam/teacher-bff/teacher-portal | **P2 身份阶段完整实现**:(1) Gateway 公开路径白名单(register/login/refresh)解决无 token 死锁。(2) IAM schema 扩展:users 加 dataScope,新增 role_viewports 表。(3) RBAC 端点 4 个 GET。(4) 视口按 requiredPermission 过滤 + sortOrder 排序;getEffectivePermissions 用 Set 去重。(5) JWT payload 含 dataScope,register 自动分配 teacher 角色。(6) 种子数据 7 权限+12 映射+7 视口。(7) Teacher BFF 视口聚合。(8) 前端:lib/auth.ts + login + AppShell + (app) 路由组 + dashboard + classes(真实 JWT)+ 根重定向。(9) E2E 全链路通过。**学到**:Next.js 路由组 (app) 不影响 URL,/login 与 /dashboard 共存只后者套壳;fetch headers 函数返回 Record<string,string> 避免 TS2769;ESLint 9 需 flat config 留 P6;AppShell aside 用 flex flex-col + mt-auto 比 absolute 稳健。 |
|
||||
| 2026-07-08 | 晚上 | iam/classes/api-gateway | **P1 端到端链路验证 + IAM 服务修复**:验证 register → JWT → Gateway /iam/me → Gateway /classes CRUD → teacher-portal 前端渲染全链路打通。(1) IAM 服务 14 个 TS 编译错误修复:移除 typeorm/ioredis/kafkajs 依赖(IAM 用 Drizzle),health.controller.ts 改用 `db.execute(sql\`SELECT 1\`)`,lifecycle.service.ts 简化为只关闭 Drizzle 连接池;Drizzle API 修正(`r.roles`→`r.iam_roles`,`.in()`→`inArray()`)。(2) NestJS ESM DI 修复:iam.module.ts 简化 providers 为 `[IamService, IamRepository]`,iam.service.ts 构造器加 `@Inject(IamRepository)`(参考 classes 黄金模板),修复运行时 `Cannot read properties of undefined (reading 'findUserByEmail')`。(3) Gateway /iam/me 404 修复:iam.controller.ts 直接读 `req.headers['x-user-id']`替代未注册的`AuthenticatedRequest`。(4) 创建 `scripts/iam-init.sql`建 6 张 IAM 表 + 种子数据。(5) E2E 验证:iam:3002 注册/登录 → Gateway /iam/me 200 → Gateway GET /classes 200 → Gateway POST /classes(合法 UUID gradeId)201 → teacher-portal:3000 首页渲染 200 + 含"班级管理" → Next.js rewrites 透传 dev-token 到 Gateway 全链路通。**学到**:NestJS ESM 模式下 DI 无法通过类型推断解析 token,必须显式`@Inject(Token)`;Drizzle select 返回字段名按 schema 定义而非表名;classes.dto.ts 的 gradeId 要求 UUID 格式,测试数据不能用 "grade-12" 这类字符串;PowerShell 控制台中文显示为 `?`是编码问题,数据库实际存储正确;DEV_MODE 下前端用`Bearer dev-token` 即可走通链路,无需真实 JWT。 |
|
||||
|
||||
Reference in New Issue
Block a user