forked from baskbuddy/zhangshun
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7.8 KiB
7.8 KiB
N07 消息撤回与会话一致性:独立代码复验与真实 MySQL/Docker 验收
日期:2026-09-10
分支:feat/message-recall
结论:PASS(真实 MySQL/Docker 黑盒已完成;可进入精确暂存检查点)
1. Git 基线与边界
- 当前分支:
feat/message-recall。 - HEAD:
dbd27e6 feat: enhance candidate scoring explanations。 - 验收开始及结束时暂存区均为空;既有 N07 修改、历史脚本、日志、JSON、SQL、xlsx 和
.env均保留。 git diff --check:通过;迁移目录没有 V1–V40 修改。- N07 唯一新增迁移:
V41__message_recall.sql。 - 未执行
git add -A、commit、push、reset、restore、checkout、clean;未删除或移动历史文件。
2. 自动化独立复验
| 命令 | Tests run | Failures | Errors | Skipped | 结果 |
|---|---|---|---|---|---|
| N07 定向测试 | 30 | 0 | 0 | 0 | BUILD SUCCESS |
| 消息与邀约关联回归 | 80 | 0 | 0 | 0 | BUILD SUCCESS |
mvn clean verify |
1601 | 0 | 0 | 0 | BUILD SUCCESS |
python docs\\verify_openapi.py 通过,静态 OpenAPI 为 173 paths / 211 operations。
3. 代码审查
- 状态机:PASS。V41 CHECK 仅允许 SENT/RECALLED;条件更新包含 messageId、conversationId、senderUserId、SENT、expectedVersion;正文固定占位、recalledAt 非空、version 仅递增一次;重复撤回幂等且不重复成功审计。
- 权限与归属:PASS。真实 HTTP 中原发送者成功,另一成员/非成员/ADMIN/跨会话为 403/2002,匿名为 401,会话/消息不存在分别为 404/8305、404/8306,超时为 409/8307。
- 并发与事务:PASS。H2 独立事务测试以及真实 HTTP 两个并发请求均无 500;同消息最终 version=1、恰好一条成功审计;不同消息并发各自成功。
- 依赖注入:PASS。生产目录不存在
messageViewMapper == null、objectMapper == null、new MessageViewMapper()、new ObjectMapper()兜底。 - 审计隐私:PASS。真实 MySQL
MESSAGE_RECALLED行ip_address/user_agent均为 NULL,details 为合法 JSON 且字段严格为messageId,conversationId,conversationType,status,requestId。 - DTO/查询结构:PASS。撤回及分页路径使用白名单 DTO;会话与成员固定查询、消息分页固定查询、message_reads 一次批量查询,无逐消息 exists/find。
- 副作用:PASS。目标消息仅发生 SENT→RECALLED、占位正文、recalledAt、version+1;message_reads、conversation_members、candidate_dimension_scores、notifications、风险表内容和 version 均未改变。
4. Docker、MySQL、Flyway 与启动
- Docker Engine:Server 29.6.2;MySQL 8.4.11、Redis 7.4、RabbitMQ 3.13 容器均 healthy。未重建、删除容器或 volume。
- 真实 Flyway 查询:最新三条为 V41
message recallsuccess=1、V40enterprise talent invitationssuccess=1、V39enterprise talent discoverysuccess=1;无失败迁移、无 N07 之外迁移。 SHOW CREATE TABLE messages:status默认 SENT、recalled_at可空、version默认 0,CHECK 仅允许 SENT/RECALLED,既有外键与idx_messages_conversation_created保留;无消息历史表。- 使用
mvn clean verify生成的 JAR、dev 配置并保持ddl-auto=validate启动,日志出现Started MyDreamjobApplication,无 Flyway/schema-validation 错误。 GET /api/v1/health:HTTP 200,status=UP。- 本轮启动的应用 PID 4412(后续边界复验重启为 PID 21168)均在验收结束后正常停止;8080 已恢复空闲。Docker 未停止。
5. 真实 HTTP 主链路与权限
- DIRECT:真实发送、列表、撤回、重复撤回全部 200;撤回后 status=RECALLED、正文为固定占位、recalledAt 非空、version 0→1,重复请求不再增加 version 或审计;senderUserId 按既有语义保留。
- TALENT_INVITATION:真实发送、撤回、列表全部 200;仅返回 senderScope,不返回 senderUserId、学生 ID或 candidateKey;会话详情和会话列表中的 TALENT_INVITATION 项不返回 createdBy;撤回后正文为固定占位。
- 权限配对结果:原发送者
200/200;另一成员403/2002;非成员403/2002;ADMIN403/2002;匿名401/401;跨会话403/2002;不存在会话404/8305;不存在消息404/8306;超时409/8307。 - 递归 JSON 脱敏:DIRECT 撤回/列表、TALENT_INVITATION 撤回/列表及会话详情中的 TALENT_INVITATION 项均未发现原正文、senderUserId(TALENT)、studentUserId、candidateKey、联系方式、IP/UA、凭据等禁止字段。
6. 并发、时间与 message_reads
- 真实 MySQL HTTP 并发:同一消息两请求均 200,最终 version=1、单条审计;两条不同消息并发均 200、各 version=1、各一条审计。
- 时间:H2 正式测试覆盖 0 秒、1:59、恰好 2:00 成功及超过 2:00 最小单位失败;真实 MySQL HTTP 119 秒返回 200/200、120 秒返回 409/8307(数据库状态分别为 RECALLED/SENT),创建后立即撤回也成功。边界表达式保持
capturedNow <= createdAt.plusMinutes(2)。 - 已有
message_reads行在撤回后仍存在(精确查询=1);撤回消息不计入 unreadCount(精确查询=0),消息仍保留时间线,未新增第二条 read 行。
7. 查询预算与 EXPLAIN
- 使用真实 MySQL
performance_schema.events_statements_summary_by_digest测量正式 HTTP 列表路径,夹具规模 1、20、50 条消息:每次均为messages=2、message_reads=1、conversations=1、conversation_members=1,查询数不随消息量线性增长。 - 真实 EXPLAIN FORMAT=JSON:消息分页使用
idx_messages_conversation_created、access=ref、无 filesort/temporary;message_reads 使用 reader 索引、成员校验使用uk_conv_members;条件撤回使用 PRIMARY、access=range;未读查询使用消息索引和uk_message_reads。未新增索引。 - 说明:该 EXPLAIN 为当前验收数据的代表性计划;更大生产数据量的容量/延迟压测仍需后续授权,不以固定查询数替代性能结论。
8. RabbitMQ 与副作用
RabbitMQ ping 成功;queue.sms.verification、queue.notification、queue.audit、queue.notification.dlq 均真实存在,ready=0、unacked=0。N07 撤回未产生新增消息、通知、短信或邮件。
目标消息撤回前后稳定摘要证明:除目标消息允许的四项状态变化和一条白名单 MESSAGE_RECALLED 审计外,message_reads、会话、成员、评分快照、通知、风险治理表内容与 version 不变。
9. OpenAPI
- 静态:173 paths / 211 operations,
verify_openapi.py通过。 - 运行时:
GET /api/v1/v3/api-docs返回 173 paths / 211 operations,与静态计数一致;撤回无 requestBody,200 响应引用ApiResponseMessageResponse,分页响应引用ApiResponseMessagePageResponse。 - 未新增编辑、删除、批量撤回、恢复接口;TALENT_INVITATION 的条件性 senderScope 脱敏由真实 JSON 验证。
10. PASS/FAIL/SKIP 与剩余风险
- PASS:自动化、V41 迁移与 schema validation、启动/健康、权限、DIRECT/TALENT_INVITATION 脱敏、并发、审计隐私、message_reads/unread、只读副作用、查询预算、EXPLAIN、RabbitMQ、静态/运行时 OpenAPI。
- FAIL:0。
- SKIP:0 个核心验收项。生产级更大规模容量压测和持续运行监控不属于本轮黑盒范围,需独立性能验收,但不构成当前 N07 功能阻断。
- 不允许把本报告扩展为对 V1–V40 其他业务的全面生产保证;仅确认 N07 变更边界。
11. 最终判定
PASS:N07 独立代码复验和真实 MySQL/Docker 黑盒全部通过,可以进入精确暂存检查点。
本报告不包含数据库密码、JWT、测试账号密码、手机号、邮箱或原消息正文。验收数据仅使用本轮唯一前缀并已按精确 ID 清理;历史验收文件未删除或移动。