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

22 KiB
Raw Blame History

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

版本v3 日期2026-07-13 负责人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-13

  • 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" } }
  • /metrics 返回 Prometheus 指标graphql_requests_total + downstream_calls_total
  • 优雅降级:下游 gRPC 不可达时 resolver 返回空数据而非崩溃({ children { id } }{ data: { children: [] } }

2. 已完成工作

2.1 P0 阻塞项(已解决)

# 工作项 状态 实现详情
1 GraphQL 端点路径修复(/graphql/v1/graphql controller + yoga + module 三处路径改为 v1/graphql,对齐 api-gateway registerBffProxy 剥离策略
2 Dockerfile 构建修复pnpm-lock.yaml + husky + better-sqlite3 --no-frozen-lockfile --ignore-scriptsruntime stage 用 --ignore-workspace --ignore-scripts
3 Proto 文件路径修复4 级 → 5 级 ../ grpc.factory.ts 改用 process.cwd() 解析,兼容开发模式和生产模式
4 GraphQL Schema 扩展至 32 Query + 6 Mutation packages/shared-ts/contracts/graphql/parent-bff.graphql 已扩展,对齐 parent-portal 全部 operations
5 全部新 Query/Mutation resolver 实现 src/graphql/resolvers/extended-resolvers.ts 37 个 resolver builder
6 Legacy resolver 修复children/child/selectChild/Child.analytics index.ts + select-child.resolver.ts + child.resolver.ts 恢复并接通真实下游
7 TypeScript 类型定义扩展 src/graphql/types.ts 新增 ChildTypeChildBriefType 使用 classId/className
8 Response Mapper 更新 mapParent 增加 permissions/schoolId新增 mapChildBrief
9 JSON scalar 支持 resolvers/index.ts 新增 JSONScalar
10 pnpm build 通过 nest build 成功dist/ 产物正常

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")

Dockerfile 关键修复:

  • builder stagepnpm install --no-frozen-lockfile --ignore-scripts(跳过 husky prepare
  • runtime stagepnpm install --prod --no-frozen-lockfile --ignore-workspace --ignore-scripts(避免 workspace 解析 + 跳过 native 构建)
  • 运行时保留 packages/shared-proto + packages/shared-ts 目录结构proto/schema 加载需要)

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 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/children/myNotifications 等核心 Query 降级返回空数据。

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

# RPC 方法 用途 状态 说明
1 listGradesByStudent(studentId) 孩子成绩列表 用于 childGrades/childSummary/childDetail
2 listHomeworkByClass(classId) 班级作业列表 用于 childHomework/childSummary
3 listExamsByClass(classId) 班级考试列表 用于 childExams/childSummary
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
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=28

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
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",...},"core-edu":{"status":"down",...},"data-ana":{"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":"{ children { id name } }"}'
# {"data":{"children":[]}}

5.5 测试容器管理

# 停止测试容器
docker rm -f edu-parent-bff-test

# 查看日志
docker logs edu-parent-bff-test --tail 50

6. 关键文件路径

文件 用途
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 类型定义
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 构建(多阶段,--ignore-scripts

7. 遗留事项

# 事项 优先级 说明
1 补全 core-edu ClassService proto P1 ISSUE-008: getClass 当前返回默认值
2 补全 msg NotificationPreferences RPC P2 通知偏好查询/更新当前降级
3 补全 data-ana 各分析 RPC P2 练习/诊断/错题本/掌握度等分析类查询当前降级
4 补全 content 课程/备课/选修 RPC P2 课程计划/备课/选修查询当前降级
5 端到端联调 P1 待 iam/core-edu/data-ana/msg 服务容器就绪后执行
6 parent-bff 加入 deploy compose P1 infra/docker-compose.deploy.yml 未包含 parent-bff需补充

8. 已完成项汇总

工作项 状态 验证方式
GraphQL 端点路径修复(/v1/graphql Docker 测试 /v1/graphql 返回 200
Dockerfile 构建修复 edu/parent-bff:test 镜像构建成功
Proto 文件路径修复 容器启动日志显示 gRPC client 创建成功
GraphQL Schema 扩展32Q + 6M { __typename } 返回 Query 类型
全部 resolver 实现 { children { id } } 返回空数组(降级正常)
Legacy resolver 修复 selectChild/Child.analytics resolver 恢复
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 + downstream_calls_total

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