Files
Edu/services/parent-bff/docs/nextstep-v2.md

29 KiB
Raw Blame History

parent-bff 模块上下游依赖与工作清单Next Steps v2

版本v2 日期2026-07-14 负责人ai04 关联:


1. 概述

parent-bff 是家长端聚合层 BFFBackend For Frontend端口 3010基于 NestJS + GraphQL Yoga。负责聚合 iam / core-edu / data-ana / msg 四个下游微服务的 gRPC 接口,为 parent-portal 前端提供场景化 GraphQL API。

路由路径ARB-022 §24.4 ISSUE-003 方案 A 双 /v1 前缀):

parent-portal
  → POST /api/v1/parent/v1/graphql        (前端调用路径)
  → api-gateway registerBffProxy("parent") (剥离 /api/v1/parent)
  → parent-bff:3010 /v1/graphql            (BFF 接收路径)
  → GraphqlController @Controller("v1/graphql")

本地 Docker 测试结果2026-07-14DEV_MODE=false不使用 mock

  • TypeScript 编译零错误(tsc --noEmit -p tsconfig.test.json
  • ESLint 零错误(eslint src test
  • 单元测试 + 集成测试全通过128 tests, 13 test files
  • Docker 镜像构建成功(edu/parent-bff:test
  • 容器启动正常(端口 3010DEV_MODE=false 生产模式)
  • /healthz 返回 200liveness 通过)
  • /readyz 返回 200status=degraded下游 gRPC 不可达但 Redis up
  • /v1/graphql GraphQL 查询正常响应({ __typename }{ data: { __typename: "Query" } }
  • /v1/graphql 扩展查询正常({ myChildren { id } }{ data: { myChildren: [] } }
  • /v1/graphql Mutation 正常(mutation { markAllAsRead { count } }{ data: { markAllAsRead: { count: 0 } } }
  • /metrics 返回 Prometheus 指标graphql_requests_total + graphql_duration_seconds
  • 优雅降级:下游 gRPC 不可达时 resolver 返回空数据而非崩溃

2. 已完成工作v2 全部完成)

2.1 P0 阻塞项(已解决)

# 工作项 状态 实现详情
1 GraphQL 端点路径修复(/graphql/v1/graphql controller + yoga + module 三处路径改为 v1/graphql,对齐 api-gateway registerBffProxy 剥离策略
2 GraphQL Schema 扩展至 32 Query + 6 Mutation packages/shared-ts/contracts/graphql/parent-bff.graphql 已扩展,对齐 parent-portal 全部 operations
3 TypeScript 类型定义扩展37+ 个新类型) src/graphql/types.ts 新增 ChildBrief/ChildSummary/ChildDetail/ChildGrade/AttendanceRecord 等 37+ 类型
4 全部新 Query/Mutation resolver 实现37 个 resolver builder src/graphql/resolvers/extended-resolvers.ts 实现 21 个 Query + 6 个 Mutation resolver
5 Legacy resolver 修复children/child/selectChild/Child.analytics index.ts + select-child.resolver.ts + child.resolver.ts 恢复并接通真实下游
6 JSON scalar 支持 resolvers/index.ts 新增 JSONScalar用于 NotificationPreferences.preferences 等动态结构)
7 Response Mapper 更新 mapParent 增加 permissions/schoolId新增 mapChildBrief
8 Notification resolver 兼容旧版/新版 schema notification.resolver.ts + notification-preference.resolver.ts 同时填充两组字段
9 Dockerfile 构建修复 构建上下文改为 repo root复制 shared-proto + shared-ts + tsconfig.base.json
10 Proto/Schema 路径解析修复 grpc.factory.ts + schema.ts 改用 process.cwd() 解析,兼容开发/生产模式
11 pino 导入修复 logger.tsimport pino from "pino" 改为 import { pino } from "pino"ESM 兼容)

2.2 关键修复详情

GraphQL 端点路径ARB-022 §24.4 ISSUE-003 方案 A

文件 路径配置
src/entry/graphql.controller.ts @Controller("v1/graphql")
src/graphql/yoga.ts graphqlEndpoint: "/v1/graphql"
src/graphql/graphql.module.ts forRoutes("v1/graphql")

Proto/Schema 路径解析process.cwd() 方式):

文件 路径解析
src/graphql/schema.ts process.cwd() + ../../packages/shared-ts/contracts/graphql/parent-bff.graphql
src/clients/grpc/grpc.factory.ts process.cwd() + ../../packages/shared-proto/proto

Dockerfile 关键修复:

  • 构建上下文改为 repo root访问 packages/shared-proto + packages/shared-ts
  • 复制 tsconfig.base.jsontsconfig.json extends ../../tsconfig.base.json
  • runtime stage--ignore-workspace --ignore-scripts(避免 workspace 解析 + 跳过 native 构建)
  • 运行时保留 packages/shared-proto + packages/shared-ts 目录结构

3. 上游依赖(调用 parent-bff 的模块)

3.1 api-gatewayai01 负责)— P0

# 依赖项 用途 状态
1 /api/v1/parent/* 反向代理路由 前端请求经 api-gateway 代理到 parent-bff:3010
2 registerBffProxy("parent", ...) 路径重写 剥离 /api/v1/parent,转发剩余路径(/v1/graphql)到 parent-bff
3 JWT 鉴权 + x-user-* 头注入 api-gateway 校验 JWT 后注入 x-user-id/x-user-roles/x-data-scope/x-trace-id
4 CORS 白名单 CORS_ORIGINS 环境变量配置
5 限流IP 级令牌桶) 100 rps突发 20
6 熔断(下游 5xx 触发) CircuitBreaker("downstream")

验证要点:

  • api-gateway 入站 /api/v1/parent/v1/graphql → 剥离 /api/v1/parent → 转发 /v1/graphql 到 parent-bff:3010
  • parent-bff GraphqlController 注册在 /v1/graphql,接收路径匹配
  • 经 api-gateway 代理访问 http://api-gateway:8080/api/v1/parent/v1/graphql 应返回 200

3.2 parent-portalai15 负责)— P0

# 依赖项 用途 状态
1 NEXT_PUBLIC_GRAPHQL_ENDPOINT 配置 前端 GraphQL 客户端调用 /api/v1/parent/v1/graphql
2 32 个 Query + 6 个 Mutation operations 前端定义的 GraphQL 操作,需 parent-bff schema 对齐
3 Mock 数据禁用 NEXT_PUBLIC_API_MOCKING=disabled,使用真实后端

前端调用路径:

parent-portal → POST /api/v1/parent/v1/graphql
  → api-gateway 剥离 /api/v1/parent
  → parent-bff:3010/v1/graphql

4. 下游依赖parent-bff 调用的模块)

4.1 iam 服务ai06 负责gRPC :50052— P0

# RPC 方法 用途 状态 说明
1 getUserInfo(userId) 获取家长个人信息 GrpcIamClient.getUserInfo,用于 me/currentUser Query
2 getChildrenByParent(parentId) 获取家长绑定的孩子列表 GrpcIamClient.getChildrenByParentChildGuard 缓存 30s
3 getViewports(userId) 获取家长可见视口 GrpcIamClient.getViewports
4 getEffectivePermissions(userId) 获取家长有效权限 GrpcIamClient.getEffectivePermissions
5 GET /healthz 端点 /readyz 下游健康检查 iam 服务容器未运行,/readyz 报告 down
6 GET /.well-known/jwks.json RS256 公钥集api-gateway 用) iam 服务容器未运行

环境变量: IAM_GRPC_TARGET=iam:50052Docker 网络)/ localhost:50052(本地开发)

影响: iam 不可达时,me/currentUser/children/myChildren 等核心 Query 降级返回空数据。

4.2 core-edu 服务ai07 负责gRPC :50053— P0

# RPC 方法 用途 状态 说明
1 listGradesByStudent(studentId) 孩子成绩列表 用于 childGrades/childSummary/childDetail
2 listHomeworkByClass(classId) 班级作业列表 用于 childHomework/childSummary/childDetail
3 listExamsByClass(classId) 班级考试列表 用于 childExams/childSummary/childDetail
4 getClass(classId) 班级信息 ⚠️ ISSUE-008: proto 缺 ClassService当前返回默认值
5 GET /healthz 端点 /readyz 下游健康检查 core-edu 服务容器未运行

环境变量: CORE_EDU_GRPC_TARGET=core-edu:50053Docker 网络)/ localhost:50053(本地开发)

降级查询: childAttendance/childExamResult/childReportCard/childLeaveRequests/academicYears/childClasses/createLeaveRequest/exportChildGrades 在 RPC 未就绪时降级返回空数据。

4.3 data-ana 服务ai09 负责gRPC :50055— P1

# RPC 方法 用途 状态 说明
1 getStudentWeakness(studentId, subjectId) 学生薄弱知识点 用于 childWeakness/childAnalytics
2 getLearningTrend(studentId, start, end) 学习趋势 用于 childTrend/childAnalytics
3 getClassPerformance(classId, subjectId, ...) 班级绩效 用于 classRank/classAverage 计算
4 GET /healthz 端点 /readyz 下游健康检查 data-ana 服务容器未运行

环境变量: DATA_ANA_GRPC_TARGET=data-ana:50055Docker 网络)/ localhost:50055(本地开发)

降级查询: childGrowthArchive/childLearningPath/childErrorBookStats/childTopWrongQuestions/childWeakKps/childMasterySummary/childDiagnosticReports/childPracticeStats/childPracticeSessions 在 RPC 未就绪时降级返回空数据。

4.4 msg 服务ai08 负责gRPC :50056— P1

# RPC 方法 用途 状态 说明
1 listNotifications(parentId, unread) 通知列表 用于 myNotifications/notifications
2 markAsRead(notificationId) 标记已读 用于 markAsRead/markAllAsRead Mutation
3 getNotificationPreferences(parentId) 通知偏好 ⚠️ proto 未定义 RPCgRPC 实现返回默认值
4 updateNotificationPreferences(...) 更新通知偏好 ⚠️ proto 未定义 RPCgRPC 实现返回输入
5 GET /healthz 端点 /readyz 下游健康检查 msg 服务容器未运行

环境变量: MSG_GRPC_TARGET=msg:50056Docker 网络)/ localhost:50056(本地开发)

4.5 Redis基础设施— P0

# 依赖项 用途 状态
1 redis://...:6379 ChildGuard 缓存 + dashboard/grades/permissions 缓存

环境变量: REDIS_URL=redis://edu-redis:6379Docker 网络)/ redis://localhost:6379(本地开发)

验证结果: 容器内 Redis 连接成功(/readyz 报告 redis:uplatency_ms=30

4.6 降级模式说明

以下 Query 在下游 RPC 未就绪时降级返回空数据(不阻塞前端渲染):

Query 降级行为 待补全的下游 RPC
childAttendance 返回空数组 core-edu AttendanceService
childExamResult 返回 null core-edu ExamResultService
childReportCard 返回 null core-edu ReportCardService
childGrowthArchive 返回空 dataPoints data-ana GrowthArchiveService
childLearningPath 返回空数组 data-ana LearningPathService
childErrorBookStats 返回零值 data-ana ErrorBookService
childTopWrongQuestions 返回空数组 data-ana ErrorBookService
childWeakKps 返回空数组 data-ana WeakKpsService
childMasterySummary 返回零值 data-ana MasteryService
childDiagnosticReports 返回空数组 data-ana DiagnosticService
childPracticeStats 返回零值 data-ana PracticeService
childPracticeSessions 返回空数组 data-ana PracticeService
childCoursePlans 返回空数组 content CoursePlanService
childCoursePlanDetail 返回 null content CoursePlanService
childLessonPlans 返回空数组 content LessonPlanService
childLessonPlanDetail 返回 null content LessonPlanService
childElective 返回空数组 content ElectiveService
childLeaveRequests 返回空数组 core-edu LeaveRequestService
academicYears 返回空数组 core-edu AcademicYearService
childClasses 返回空数组 classes ClassService
createLeaveRequest 返回 PENDING 状态 core-edu LeaveRequestService
exportChildGrades 返回临时 URL core-edu ExportService

5. Docker 本地测试

5.1 镜像构建

# 在仓库根目录执行(需要访问 packages/shared-proto + packages/shared-ts + tsconfig.base.json
docker build -t edu/parent-bff:test -f services/parent-bff/Dockerfile .

5.2 容器启动

# 加入 edu-full_default 网络(与 Redis/MySQL/Kafka 等基础设施同网络)
docker run -d \
  --name edu-parent-bff-test \
  --network edu-full_default \
  -p 3010:3010 \
  -e NODE_ENV=production \
  -e DEV_MODE=false \
  -e PORT=3010 \
  -e REDIS_URL=redis://edu-redis:6379 \
  -e IAM_GRPC_TARGET=iam:50052 \
  -e CORE_EDU_GRPC_TARGET=core-edu:50053 \
  -e DATA_ANA_GRPC_TARGET=data-ana:50055 \
  -e MSG_GRPC_TARGET=msg:50056 \
  -e CORS_ORIGINS=http://localhost:4002 \
  -e GRAPHQL_INTROSPECTION_ENABLED=true \
  edu/parent-bff:test

5.3 健康检查验证

# liveness返回 200
curl http://localhost:3010/healthz
# {"status":"ok","service":"parent-bff","timestamp":"..."}

# readiness返回 200status=degraded 因为下游 gRPC 不可达)
curl http://localhost:3010/readyz
# {"status":"degraded","checks":{"iam":{"status":"down",...},"redis":{"status":"up",...}}}

# Prometheus 指标
curl http://localhost:3010/metrics

5.4 GraphQL 端点验证

# 必须携带 x-user-* 头api-gateway 注入)
curl -X POST http://localhost:3010/v1/graphql \
  -H "Content-Type: application/json" \
  -H "x-user-id: parent-001" \
  -H "x-user-roles: parent" \
  -H "x-data-scope: CHILDREN:child-001" \
  -H "x-trace-id: test-trace-001" \
  -d '{"query":"{ __typename }"}'
# {"data":{"__typename":"Query"}}

# 扩展查询(优雅降级)
curl -X POST http://localhost:3010/v1/graphql \
  -H "Content-Type: application/json" \
  -H "x-user-id: parent-001" \
  -H "x-user-roles: parent" \
  -d '{"query":"{ myChildren { id name } }"}'
# {"data":{"myChildren":[]}}

# Mutation
curl -X POST http://localhost:3010/v1/graphql \
  -H "Content-Type: application/json" \
  -H "x-user-id: parent-001" \
  -H "x-user-roles: parent" \
  -d '{"query":"mutation { markAllAsRead { count } }"}'
# {"data":{"markAllAsRead":{"count":0}}}

6. 后续其他模块配合工作

6.1 待下游服务补全的 RPCP1

服务 待补全 RPC 用途 影响 Query/Mutation
core-edu AttendanceService.ListAttendance 孩子考勤记录 childAttendance
core-edu ExamResultService.GetExamResult 考试成绩详情 childExamResult
core-edu ReportCardService.GetReportCard 成绩单 childReportCard
core-edu LeaveRequestService.List/Create 请假记录 childLeaveRequests/createLeaveRequest
core-edu AcademicYearService.List 学年列表 academicYears
core-edu ClassService.GetClass 班级信息ISSUE-008 childClasses
core-edu ExportService.ExportGrades 成绩导出 exportChildGrades
data-ana GrowthArchiveService.Get 成长档案 childGrowthArchive
data-ana LearningPathService.List 学习路径 childLearningPath
data-ana ErrorBookService.GetStats/List 错题本统计/列表 childErrorBookStats/childTopWrongQuestions
data-ana WeakKpsService.List 薄弱知识点 childWeakKps
data-ana MasteryService.GetSummary 掌握度汇总 childMasterySummary
data-ana DiagnosticService.List 诊断报告 childDiagnosticReports
data-ana PracticeService.GetStats/List 练习统计/会话 childPracticeStats/childPracticeSessions
content CoursePlanService.List/Get 课程计划 childCoursePlans/childCoursePlanDetail
content LessonPlanService.List/Get 备课计划 childLessonPlans/childLessonPlanDetail
content ElectiveService.List 选修课 childElective
msg NotificationPreferencesService 通知偏好查询/更新 myNotificationPreferences/updateMyNotificationPreferences

6.2 端到端联调待办P1

# 联调项 触发条件
1 iam 服务容器启动 + JWKS 端点就绪 iam 服务 Docker 化
2 core-edu 服务容器启动 + gRPC 端口就绪 core-edu 服务 Docker 化
3 data-ana 服务容器启动 + gRPC 端口就绪 data-ana 服务 Docker 化
4 msg 服务容器启动 + gRPC 端口就绪 msg 服务 Docker 化
5 parent-bff 加入 deploy compose infra/docker-compose.deploy.yml 补充 parent-bff 服务定义
6 parent-portal → api-gateway → parent-bff 端到端 所有服务容器就绪后执行

6.3 给下游模块的工作要求

给 iamai06

  • 补全 getChildrenByParent RPC返回 ChildDto 列表,含 id/name/grade/classId/className/gradeId
  • 补全 getViewports RPC返回 ViewportDto 列表)
  • 补全 getEffectivePermissions RPC返回 permissions 数组)
  • 启动 /healthz 端点供 parent-bff /readyz 探测

给 core-eduai07

  • 补全 ClassService.GetClass RPCISSUE-008 仲裁)
  • 补全 AttendanceService/ExamResultService/ReportCardService/LeaveRequestService/AcademicYearService/ExportService
  • 启动 /healthz 端点供 parent-bff /readyz 探测

给 data-anaai09

  • 补全 GrowthArchiveService/LearningPathService/ErrorBookService/WeakKpsService/MasteryService/DiagnosticService/PracticeService
  • 启动 /healthz 端点供 parent-bff /readyz 探测

给 msgai08

  • 补全 NotificationPreferencesServiceGet/Update
  • 启动 /healthz 端点供 parent-bff /readyz 探测

给 api-gatewayai01

  • 确认 /api/v1/parent/* 路由已注册(已完成)
  • 确认 registerBffProxy("parent", ...) 路径重写剥离 /api/v1/parent(已完成)

给 parent-portalai15

  • 确认 NEXT_PUBLIC_GRAPHQL_ENDPOINT=/api/v1/parent/v1/graphql(已完成)
  • 确认 32 Query + 6 Mutation operations 与 parent-bff.graphql schema 对齐(已完成)

7. 关键文件路径

文件 用途
packages/shared-ts/contracts/graphql/parent-bff.graphql GraphQL Schema 契约32Q + 6M前后端共享唯一源
services/parent-bff/src/entry/graphql.controller.ts Controller路由 v1/graphql
services/parent-bff/src/graphql/yoga.ts Yoga 实例(端点 /v1/graphql
services/parent-bff/src/graphql/graphql.module.ts Module中间件路由 v1/graphql
services/parent-bff/src/graphql/schema.ts SDL 加载process.cwd() 解析路径)
services/parent-bff/src/graphql/resolvers/index.ts Resolver 注册(含 DateTime + JSON scalar
services/parent-bff/src/graphql/resolvers/extended-resolvers.ts 37 个新 resolver builder
services/parent-bff/src/graphql/resolvers/child.resolver.ts legacy childAnalytics resolver
services/parent-bff/src/graphql/resolvers/select-child.resolver.ts legacy selectChild Mutation resolver
services/parent-bff/src/graphql/types.ts TypeScript 类型定义37+ 个新类型)
services/parent-bff/src/aggregation/response-mapper.ts DTO → GraphQL Type 映射
services/parent-bff/src/clients/grpc/grpc.factory.ts gRPC 客户端工厂process.cwd() 解析 proto 路径)
services/parent-bff/src/config/env.ts Zod 环境变量校验
services/parent-bff/Dockerfile Docker 构建多阶段repo root 上下文)

8. 已完成项汇总

工作项 状态 验证方式
GraphQL 端点路径修复(/v1/graphql Docker 测试 /v1/graphql 返回 200
GraphQL Schema 扩展32Q + 6M { __typename } 返回 Query 类型
TypeScript 类型定义扩展37+ 个新类型) tsc --noEmit 零错误
全部 resolver 实现37 个 resolver builder { myChildren { id } } 返回空数组(降级正常)
Legacy resolver 修复 selectChild/Child.analytics resolver 恢复
JSON scalar 支持 NotificationPreferences.preferences 字段可用
Response Mapper 更新 mapParent 含 permissions/schoolIdmapChildBrief 新增
Notification resolver 兼容旧版/新版 schema 同时填充 type/content 和 eventType/body
Dockerfile 构建修复 edu/parent-bff:test 构建成功
Proto/Schema 路径解析修复 容器启动日志显示 gRPC client 创建成功
pino 导入修复 容器启动无错误
TypeScript 编译零错误 tsc --noEmit -p tsconfig.test.json 通过
ESLint 零错误 eslint src test 通过
单元测试 + 集成测试通过 128 tests, 13 test files 全部通过
Docker 镜像构建 edu/parent-bff:test 构建成功
Docker 容器运行验证 /healthz 200 + /readyz 200 + /v1/graphql 200 + /metrics 200
优雅降级验证 下游 gRPC 不可达时返回空数据而非崩溃
可观测性验证 /metrics 含 graphql_requests_total + graphql_duration_seconds
Mutation 验证 markAllAsRead { count } 返回 0

本文件由 ai04 维护。parent-bff 已完成 v2 全部工作并通过本地 Docker 测试DEV_MODE=false连接真实 Redis下游 gRPC 不可达时优雅降级。等待下游应用服务iam/core-edu/data-ana/msg容器就绪后即可端到端联调。