完成阶段六迭代一运行边界加固及阶段五后续收口 - #5
Merged
Merged
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
运行态 compose 校验脚本与本地 manifest 校验存在可复现的边界回归(空容器 ID 误判、IPv6 localhost 未被允许),需修正后再合入。
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
本 PR 延续阶段五收口并完成阶段六迭代一(S6-01/S6-02),核心聚焦在运行边界加固(Compose/运行态校验/优雅停机)与数据库繁忙退化为统一 503(含 OpenAPI/客户端同步),同时将音乐清单来源迁移为“Studio 可配置 + 环境回退”,并把 404 彩蛋从“修复小游戏”升级为“游戏中心”。
Changes:
- 强化生产 Compose 运行边界:禁用容器 Swap、API/Web 只读根目录 + 有界 tmpfs、明确 stop_grace_period,并在 CI 复用脚本做运行态白名单/cgroup 校验。
- API 侧统一数据库繁忙/超时为
503 DATABASE_BUSY(附Retry-After: 2、Cache-Control: no-store),同步 OpenAPI 与生成的 TS 客户端;同时对连接池/SQL/锁等待做强约束与测试覆盖。 - Web 侧:音乐控制台改为直接拉取站点配置的 manifest URL;评论改为即时发布并回刷;404 引入按交互懒加载的游戏中心(贪吃蛇/2048/扫雷)并补齐单测与 E2E。
File summaries
| File | Description |
|---|---|
| scripts/verify-compose-resources.mjs | 扩展为同时验证 compose config 与运行态(docker inspect + cgroup v2)资源/权限边界 |
| README.md | 更新阶段能力说明与运行边界摘要 |
| packages/api-client/src/generated.ts | 同步 OpenAPI:新增 DatabaseBusy 响应、站点 musicManifestUrl、评论即时发布语义等 |
| infra/compose/compose.prod.yml | 生产 Compose:memswap_limit 禁用 swap、stop_grace_period、API/Web 只读根目录 + tmpfs 等 |
| docs/本地启动指南.md | 增补阶段六运行边界说明与验证命令/注意事项 |
| docs/openapi/public-api.yaml | 增加 DatabaseBusy 响应并广泛挂载到 public/admin 路由;站点响应新增 musicManifestUrl |
| docs/HaoBlog-design-language.md | 更新 404 彩蛋描述为“游戏中心”并明确降级/懒加载策略 |
| apps/web/test/phase5-static-boundaries.test.ts | 更新静态边界回归:音乐组件改名、404 入口变更 |
| apps/web/test/music-and-game-regressions.test.ts | 新增音乐音量缓存与小游戏键盘事件不抢占输入控件回归测试 |
| apps/web/test/error-games.test.ts | 新增 2048/扫雷核心逻辑单测 |
| apps/web/test/comment-signal.test.ts | 评论状态从待审改为已发布的回归更新 |
| apps/web/server/routes/music-manifest.json.get.ts | 移除 server route 代理 manifest(改为直连站点配置 URL) |
| apps/web/scripts/check-article-client-bundle.mjs | 更新文章路由 bundle 探针关键字(MusicConsole) |
| apps/web/e2e/stage5.spec.ts | 更新音乐与 404 游戏中心相关 E2E;manifest 改为站点下发 URL |
| apps/web/e2e/stage4.spec.ts | 评论提交由 202/PENDING 改为 201/APPROVED;Studio 文案与站点设置契约同步 |
| apps/web/app/utils/publicSite.ts | public site 默认值新增 musicManifestUrl: null |
| apps/web/app/utils/errorGames.ts | 新增 2048/扫雷工具函数与键盘事件忽略策略 |
| apps/web/app/pages/studio/settings.vue | Studio 设置新增音乐清单 URL 字段与浏览器侧校验 |
| apps/web/app/pages/studio/comments.vue | Studio “评论审核”改为“评论管理”及文案同步 |
| apps/web/app/pages/articles/[slug].vue | 评论发布后触发刷新(@published -> refreshComments) |
| apps/web/app/layouts/studio.vue | Studio 导航文案更新(评论管理) |
| apps/web/app/layouts/default.vue | 音乐入口改为 MusicConsole,依赖站点下发 manifestUrl,并维护 open 状态 |
| apps/web/app/error.vue | 404 增强改为“游戏中心”按交互懒加载入口 |
| apps/web/app/components/music/SignalTape.client.vue | 删除旧 SignalTape 播放器实现 |
| apps/web/app/components/music/MusicConsole.client.vue | 新增 MusicConsole(dialog 控制台 + 频谱可选 + CORS 回退) |
| apps/web/app/components/error/SnakeGame.client.vue | 新增贪吃蛇小游戏组件 |
| apps/web/app/components/error/SignalRepair.client.vue | 删除旧“信号修复”小游戏组件 |
| apps/web/app/components/error/MinesweeperGame.client.vue | 新增扫雷小游戏组件 |
| apps/web/app/components/error/Game2048.client.vue | 新增 2048 小游戏组件 |
| apps/web/app/components/error/ErrorGameCenter.client.vue | 新增 404 游戏中心(选择器 + Suspense 懒加载) |
| apps/web/app/components/articles/CommentSignalSection.vue | 评论提交状态改为 published 并发出 published 事件 |
| apps/api/src/test/java/io/haoblog/ToolAdminIT.java | IT 增加 DirtiesContext(隔离上下文副作用) |
| apps/api/src/test/java/io/haoblog/site/application/SiteServiceTest.java | 新增 manifest URL 存储/回退与 URL 校验测试 |
| apps/api/src/test/java/io/haoblog/PublicApiIT.java | IT 增加 DirtiesContext |
| apps/api/src/test/java/io/haoblog/MediaUploadIT.java | 大幅增强边界/并发/连接池/SMTP/Outbox/锁等待等集成验证 |
| apps/api/src/test/java/io/haoblog/media/application/MediaUploadServiceTest.java | 构造参数变更:注入事务管理器(mock)以适配新实现 |
| apps/api/src/test/java/io/haoblog/GardenGraphIT.java | IT 增加 DirtiesContext |
| apps/api/src/test/java/io/haoblog/ContentModelIT.java | Flyway 版本计数更新;评论默认状态改为 APPROVED 的断言同步 |
| apps/api/src/test/java/io/haoblog/comment/application/CommentServiceTest.java | 评论创建语义从 pending 改为 approved;测试命名同步 |
| apps/api/src/test/java/io/haoblog/comment/application/CommentNotificationOutboxProcessorTest.java | Outbox “单条认领 + findByIdForUpdate + attempt 防覆盖” 行为回归 |
| apps/api/src/test/java/io/haoblog/comment/application/CommentNotificationMailerTest.java | Mailer 构造参数/文案更新(审核->管理、待审->已发布) |
| apps/api/src/test/java/io/haoblog/ArticleWorkflowIT.java | IT 增加 DirtiesContext |
| apps/api/src/test/java/io/haoblog/AdminSessionIT.java | IT 增加 DirtiesContext |
| apps/api/src/test/java/io/haoblog/AdminContentIT.java | IT 增加 DirtiesContext |
| apps/api/src/test/java/io/haoblog/AdminCommentIT.java | IT 增加 DirtiesContext |
| apps/api/src/main/resources/db/migration/V17__instant_comments_and_music_manifest.sql | schema:评论默认状态 APPROVED;site_setting 新增 music_manifest_url |
| apps/api/src/main/resources/application.yml | 优雅停机与超时;Hikari/SQL/锁等待边界;Flyway 独立连接;SMTP socketFactory 截止等 |
| apps/api/src/main/java/io/haoblog/site/web/PublicSiteController.java | public site 响应新增 musicManifestUrl |
| apps/api/src/main/java/io/haoblog/site/web/AdminSiteController.java | admin site 更新请求新增 musicManifestUrl 并写入 |
| apps/api/src/main/java/io/haoblog/site/domain/SiteSetting.java | SiteSetting 新增 musicManifestUrl 字段 |
| apps/api/src/main/java/io/haoblog/site/application/SiteService.java | manifest URL:DB 优先、环境回退;更新时校验并用于 public/admin 输出 |
| apps/api/src/main/java/io/haoblog/shared/web/GlobalExceptionHandler.java | DB 超时/锁等待/连接失败统一映射为 503 DATABASE_BUSY + headers |
| apps/api/src/main/java/io/haoblog/shared/outbox/OutboxEventStateService.java | Outbox 改为单条认领;markProcessed/markFailed 使用 attempt 防止覆盖 |
| apps/api/src/main/java/io/haoblog/shared/outbox/OutboxEventRepository.java | 增加 findByIdForUpdate(悲观锁) |
| apps/api/src/main/java/io/haoblog/media/application/MediaUploadService.java | complete 改为事务外做 OSS HEAD,事务内做锁定/落库(减少连接与行锁占用) |
| apps/api/src/main/java/io/haoblog/comment/web/PublicCommentController.java | 评论创建返回码从 202 改为 201 |
| apps/api/src/main/java/io/haoblog/comment/infrastructure/DeadlineSmtpSocketFactory.java | 新增 SMTP 套接字 15s 总期限关闭机制 |
| apps/api/src/main/java/io/haoblog/comment/domain/Comment.java | 评论默认状态从 PENDING 改为 APPROVED |
| apps/api/src/main/java/io/haoblog/comment/application/CommentService.java | honeypot “接受但不落库” 的返回状态同步为 APPROVED;正常创建返回实际状态 |
| apps/api/src/main/java/io/haoblog/comment/application/CommentNotificationOutboxProcessor.java | 调度频率改为 1s;状态更新带 attempt 防覆盖 |
| apps/api/src/main/java/io/haoblog/comment/application/CommentNotificationMailer.java | 事务外发送 SMTP;事务内只读准备邮件;文案更新 |
| AGENTS.md | 补充运行态 compose 验证命令(带 project 参数) |
| .github/workflows/ci.yml | CI 用 verify-compose-resources.mjs 替换零散 docker inspect 断言 |
Review details
- Files reviewed: 64/64 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
本 PR 保留尚未进入 main 的前置提交 0c292f1(评论即时发布、音乐控制台和 404 游戏中心),并完成阶段六迭代一 S6-01 / S6-02。旧 PR #4 已合并,本 PR 接续其后续改动。
验证:本地 API verify 86 项、PostgreSQL/pgvector Failsafe 61 项通过;Web typecheck、109 项测试和生产构建通过;api-client check、两套 Compose 配置及 compose:verify 通过。新增真实连接占用、行锁、慢 SMTP、并发完成、过期复核、租约重试和发布/Session 补偿测试。专用真正 prod profile 的 TLS、会话、写入、重启和停机 Smoke 通过。提交前再次运行 compose:verify、api-client check、git diff --check 均通过。
限制:开发机资源限制检查仅为预验收;2 核/2 GiB 持续负载、真实外部服务和部署未验收。系统 DNS 解析及跨入口错误统一仍待后续阶段。无新增生产服务;前置提交包含 V17,阶段六加固本身无 schema 变更,不开始迭代二。私有验收资料与本地部署配置未提交。
远端验收:最终提交 395e98f 的 CI #59 全部检查通过:API 86 项、Failsafe 61 项、Web 109 项,类型/构建/契约、完整 Linux Dockerfile 构建、四容器运行态、Smoke、包预算和两条 Lighthouse 路由。Chromium E2E 25 项通过、1 项按既有条件跳过(AudioContext 测试需要 HAOBLOG_MUSIC_TEST 专用音乐配置)。三条审查意见已修复并添加 IPv6 回归验证。