feat(student-bff): extended queries/mutations resolvers + Dockerfile + nextstep 文档
This commit is contained in:
199
services/student-bff/docs/nextstep.md
Normal file
199
services/student-bff/docs/nextstep.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# student-bff 下游工作清单(Next Steps)
|
||||
|
||||
> 负责人:ai04
|
||||
> 更新日期:2026-07-13
|
||||
> 关联:[student-portal_contract.md](../../docs/architecture/issues/contracts/student-portal_contract.md)、[student-portal_workline.md](../../docs/architecture/issues/worklines/student-portal_workline.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
|
||||
student-bff 已完成全部 35 Query + 23 Mutation + 1 Subscription 的 schema 与 resolver 实现,Docker 镜像本地构建与运行验证通过(`MOCK_UPSTREAM=false`)。下游 gRPC 服务未启动时,BFF 进入降级模式(方案 B),返回 `degraded: true` + `degradedReason` + `degradedFields`。
|
||||
|
||||
**本地 Docker 测试结果(2026-07-13):**
|
||||
|
||||
- ✅ 镜像构建成功(`edu/student-bff:test`)
|
||||
- ✅ 容器启动正常(端口 3009,NestFactory + GraphQL Yoga 初始化完成)
|
||||
- ✅ `/healthz` 返回 200
|
||||
- ✅ `MOCK_UPSTREAM=false`,下游未启动时进入降级模式
|
||||
- ✅ `serverTime` Query 返回本地时间(无下游依赖)
|
||||
- ✅ `myProfile` Query 返回 `degraded=true`,原因为 `DOWNSTREAM_FAILURE: iam.GetUserProfile failed after 3 attempts`
|
||||
- ✅ `mySchedule` Query 返回空 items + `degraded=true`
|
||||
- ✅ `markAsRead` Mutation 返回 `success=false` + `error.code=BFF_STUDENT_BAD_GATEWAY`
|
||||
- ✅ `createLeaveRequest` Mutation 返回 `success=false` + `error.code=BFF_STUDENT_BAD_GATEWAY`
|
||||
- ✅ B4 越权防御生效:无 `x-user-id` header 时返回 401 UnauthorizedError
|
||||
- ✅ Kafka 软失败(不影响服务启动,仅 EventSubscriber 不工作)
|
||||
|
||||
---
|
||||
|
||||
## 2. 上游依赖(api-gateway 路由)
|
||||
|
||||
### 2.1 api-gateway(ai01 负责)
|
||||
|
||||
**阻塞级别:P0(必须完成才能端到端联调)**
|
||||
|
||||
| # | 工作项 | 详情 |
|
||||
| --- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| 1 | 新增 `/api/v1/student/graphql` 路由 | 当前 api-gateway 无此路由。需新增 POST `/api/v1/student/graphql` 代理到 student-bff :3009/graphql(ARB-019 §21) |
|
||||
| 2 | JWT 校验 + 用户身份注入 | api-gateway 校验 JWT 后,注入 `x-user-id` / `x-user-roles` / `x-request-id` header 到 student-bff |
|
||||
| 3 | 学生角色校验 | `/api/v1/student/*` 路由组上添加 `student` 角色门禁,拒绝非 student 角色访问 |
|
||||
| 4 | 限流配置 | student-bff 路由组配置 IP 级令牌桶限流 |
|
||||
| 5 | 熔断/重试 | 对 student-bff 后端配置熔断器(opossum 已在 student-bff 内部启用,gateway 层可加外层熔断) |
|
||||
|
||||
**相关文件:**
|
||||
|
||||
- `services/api-gateway/main.go`(路由注册)
|
||||
- `services/api-gateway/internal/middleware/auth.go`(JWT 校验)
|
||||
- `services/api-gateway/internal/proxy/proxy.go`(反向代理)
|
||||
- `services/api-gateway/internal/config/config.go`(路由配置)
|
||||
|
||||
---
|
||||
|
||||
## 3. 下游依赖(gRPC 微服务)
|
||||
|
||||
### 3.1 iam 服务(ai06 负责)
|
||||
|
||||
**阻塞级别:P0(影响用户身份相关功能)**
|
||||
|
||||
| # | gRPC 方法 | 用途 | 当前状态 |
|
||||
| --- | ---------------- | ------------------------- | -------- |
|
||||
| 1 | `GetUserProfile` | `myProfile` Query | ❌ 缺失 |
|
||||
| 2 | `UpdateProfile` | `updateProfile` Mutation | ❌ 缺失 |
|
||||
| 3 | `ChangePassword` | `changePassword` Mutation | ❌ 缺失 |
|
||||
|
||||
**proto 位置:** `packages/shared-proto/proto/iam/v1/iam.proto`
|
||||
|
||||
### 3.2 core-edu 服务(ai08 负责)
|
||||
|
||||
**阻塞级别:P0(影响学生核心学习功能)**
|
||||
|
||||
| # | gRPC 方法 | 用途 | 当前状态 |
|
||||
| --- | ---------------------------- | ------------------------------ | -------- |
|
||||
| 1 | `GetExam` | `examDetail` Query | ❌ 缺失 |
|
||||
| 2 | `SubmitExam` | `submitExam` Mutation | ❌ 缺失 |
|
||||
| 3 | `SaveExamDraft` | `saveExamDraft` Mutation | ❌ 缺失 |
|
||||
| 4 | `RecordExamViolation` | `recordExamViolation` Mutation | ❌ 缺失 |
|
||||
| 5 | `GetHomework` | `homeworkDetail` Query | ❌ 缺失 |
|
||||
| 6 | `GetScheduleByStudent` | `mySchedule` Query | ❌ 缺失 |
|
||||
| 7 | `ListLeaveRequestsByStudent` | `myLeaveRequests` Query | ❌ 缺失 |
|
||||
| 8 | `CreateLeaveRequest` | `createLeaveRequest` Mutation | ❌ 缺失 |
|
||||
| 9 | `CancelLeaveRequest` | `cancelLeaveRequest` Mutation | ❌ 缺失 |
|
||||
| 10 | `GetReportCard` | `myReportCard` Query | ❌ 缺失 |
|
||||
|
||||
**proto 位置:** `packages/shared-proto/proto/core_edu/v1/core_edu.proto`
|
||||
|
||||
### 3.3 content 服务(ai09 负责)
|
||||
|
||||
**阻塞级别:P0(影响学生内容浏览功能)**
|
||||
|
||||
| # | gRPC 方法 | 用途 | 当前状态 |
|
||||
| --- | --------------------------------- | -------------------------------- | -------- |
|
||||
| 1 | `ListElectiveSelectionsByStudent` | `myElectiveSelections` Query | ❌ 缺失 |
|
||||
| 2 | `ListAvailableElectiveCourses` | `availableElectiveCourses` Query | ❌ 缺失 |
|
||||
| 3 | `SelectCourse` | `selectElectiveCourse` Mutation | ❌ 缺失 |
|
||||
| 4 | `DropCourse` | `dropElectiveCourse` Mutation | ❌ 缺失 |
|
||||
| 5 | `ListLessonPlansByStudent` | `myLessonPlans` Query | ❌ 缺失 |
|
||||
| 6 | `GetLessonPlan` | `lessonPlanDetail` Query | ❌ 缺失 |
|
||||
| 7 | `ListCoursePlansByStudent` | `myCoursePlans` Query | ❌ 缺失 |
|
||||
| 8 | `GetCoursePlan` | `coursePlanDetail` Query | ❌ 缺失 |
|
||||
|
||||
**proto 位置:** `packages/shared-proto/proto/content/v1/content.proto`
|
||||
|
||||
### 3.4 data-ana 服务(ai12 负责)
|
||||
|
||||
**阻塞级别:P0(影响学生学情分析功能)**
|
||||
|
||||
| # | gRPC 方法 | 用途 | 当前状态 |
|
||||
| --- | ------------------------------- | ------------------------------- | -------- |
|
||||
| 1 | `GetStudentGrowth` | `studentGrowth` Query | ❌ 缺失 |
|
||||
| 2 | `GetAssignmentAnalysis` | `assignmentAnalysis` Query | ❌ 缺失 |
|
||||
| 3 | `GetMasterySummary` | `myMasterySummary` Query | ❌ 缺失 |
|
||||
| 4 | `ListDiagnosticReports` | `myDiagnosticReports` Query | ❌ 缺失 |
|
||||
| 5 | `ListErrorBookItems` | `myErrorBook` Query | ❌ 缺失 |
|
||||
| 6 | `ListPracticeSessionsByStudent` | `myPracticeSessions` Query | ❌ 缺失 |
|
||||
| 7 | `StartPracticeSession` | `startPracticeSession` Query | ❌ 缺失 |
|
||||
| 8 | `SubmitPracticeAnswer` | `submitPracticeAnswer` Mutation | ❌ 缺失 |
|
||||
|
||||
**proto 位置:** `packages/shared-proto/proto/data_ana/v1/data_ana.proto`
|
||||
|
||||
### 3.5 msg 服务(ai10 负责)
|
||||
|
||||
**阻塞级别:P0(影响学生通知与公告功能)**
|
||||
|
||||
| # | gRPC 方法 | 用途 | 当前状态 |
|
||||
| --- | ------------------------------ | --------------------------------------- | -------- |
|
||||
| 1 | `ListAnnouncements` | `announcements` Query | ❌ 缺失 |
|
||||
| 2 | `GetAnnouncement` | `announcementDetail` Query | ❌ 缺失 |
|
||||
| 3 | `MarkNotificationAsRead` | `markAsRead` Mutation | ❌ 缺失 |
|
||||
| 4 | `MarkAllNotificationsAsRead` | `markAllAsRead` Mutation | ❌ 缺失 |
|
||||
| 5 | `UpdateNotificationPreference` | `updateNotificationPreference` Mutation | ❌ 缺失 |
|
||||
| 6 | `MarkAnnouncementRead` | `markAnnouncementRead` Mutation | ❌ 缺失 |
|
||||
|
||||
**proto 位置:** `packages/shared-proto/proto/msg/v1/msg.proto`
|
||||
|
||||
### 3.6 ai 服务(ai11 负责)
|
||||
|
||||
**阻塞级别:P1(影响 AI 辅助功能,可降级)**
|
||||
|
||||
| # | gRPC 方法 | 用途 | 当前状态 |
|
||||
| --- | -------------- | ----------------------- | -------- |
|
||||
| 1 | `StreamAIChat` | `aiStream` Subscription | ❌ 缺失 |
|
||||
|
||||
**proto 位置:** `packages/shared-proto/proto/ai/v1/ai.proto`
|
||||
|
||||
### 3.7 push-gateway(ai13 负责)
|
||||
|
||||
**阻塞级别:P1(影响实时推送)**
|
||||
|
||||
| # | 工作项 | 详情 |
|
||||
| --- | ------------------ | ---------------------------------------------------------------- |
|
||||
| 1 | WebSocket 推送端点 | student-bff EventSubscriber 接收 Kafka 事件后转发到 push-gateway |
|
||||
| 2 | Kafka topic 对齐 | student-bff 订阅 `student.notification.*` 等 topic |
|
||||
|
||||
---
|
||||
|
||||
## 4. student-bff 已完成项汇总
|
||||
|
||||
| 工作项 | 状态 | 验证方式 |
|
||||
| ------------------------------------------- | ---- | ------------------------------------------- |
|
||||
| Schema 扩展(13Q+2M → 35Q+23M+1S) | ✅ | `pnpm typecheck` + GraphQL Playground 校验 |
|
||||
| 22 个扩展 Query Resolver | ✅ | Docker 容器 GraphQL 请求测试 |
|
||||
| 21 个扩展 Mutation Resolver | ✅ | Docker 容器 GraphQL 请求测试 |
|
||||
| Zod 输入校验(21 个 Mutation Input Schema) | ✅ | typecheck + 运行时校验 |
|
||||
| B4 越权防御(assertOwnData) | ✅ | 无 `x-user-id` 返回 401 |
|
||||
| 降级模式(方案 B) | ✅ | 下游不可用时返回 `degraded=true` + 原因 |
|
||||
| Redis 缓存(B6 5-30s TTL) | ✅ | CacheService 已注入,TTL 预设已配置 |
|
||||
| Kafka EventSubscriber(软失败) | ✅ | Kafka 不可用时不阻塞启动 |
|
||||
| DataLoader 批量加载 | ✅ | createDataLoaders 已注入 context |
|
||||
| Dockerfile 多阶段构建 | ✅ | `edu/student-bff:test` 构建成功 |
|
||||
| Docker 本地测试(MOCK_UPSTREAM=false) | ✅ | healthz + GraphQL Query/Mutation 全部按预期 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 联调顺序建议
|
||||
|
||||
1. **ai06** 完成 iam gRPC(GetUserProfile / UpdateProfile / ChangePassword)
|
||||
2. **ai08** 完成 core-edu gRPC(GetExam / SubmitExam / GetHomework / GetScheduleByStudent 等 10 个)
|
||||
3. **ai09** 完成 content gRPC(8 个选修/教案/课程计划相关)
|
||||
4. **ai12** 完成 data-ana gRPC(8 个学情分析相关)
|
||||
5. **ai10** 完成 msg gRPC(6 个通知/公告相关)
|
||||
6. **ai01** 完成 api-gateway `/api/v1/student/graphql` 路由 + JWT 注入
|
||||
7. **ai11** 完成 ai gRPC StreamAIChat(P1)
|
||||
8. **ai13** 完成 push-gateway WebSocket(P1)
|
||||
9. 端到端联调(student-portal → api-gateway → student-bff → 6 个下游 gRPC 服务)
|
||||
|
||||
---
|
||||
|
||||
## 6. 已知限制
|
||||
|
||||
| # | 限制 | 说明 |
|
||||
| --- | ------------------------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| 1 | Kafka 未启动时 EventSubscriber 软失败 | 服务正常启动,但实时事件推送(通知/AI 流式响应)不工作 |
|
||||
| 2 | 下游 gRPC 未就绪时进入降级模式 | 所有 Query 返回 `degraded=true` + 空数据;所有 Mutation 返回 `success=false` + BAD_GATEWAY |
|
||||
| 3 | DEV_MODE=true 时跳过 B4 越权校验 | 生产环境必须 `DEV_MODE=false`,由 api-gateway 注入 `x-user-id` header |
|
||||
| 4 | pino-pretty 仅 devDependencies | 生产环境 `NODE_ENV=production` 时不启用 pino-pretty transport(输出结构化 JSON) |
|
||||
| 5 | OTEL_EXPORTER_OTLP_ENDPOINT 未配置 | Tracer 被禁用,需配置 OTLP endpoint 启用全链路追踪 |
|
||||
|
||||
---
|
||||
|
||||
**本文件由 ai04 维护,下游工作项请各负责 AI 完成后通知 ai04 更新状态。**
|
||||
Reference in New Issue
Block a user