Files
Wyndham-RSVN-0918/docs/project/integrations/wechat-failure-notification-cp1.md
T
鲨鱼辣椒 f4aa01e1f9
verify / booking-verify (push) Has been cancelled
完善Proposal配额处理、失败收尾及工作台历史功能
补齐C1正文资料交付和C2配额分类规则,完善Proposal人工任务、固定图片过滤及邮件附件展示。
修正失败终态与恢复上限,增加关闭状态的通知组件,永久保留处理历史并完善筛选分页。
同步相关页面修复、迁移、测试和项目记录。

验证:后台复用同源码clean verify结果1155通过/10条件跳过;前端262项及生产构建通过;敏感资料和提交路径检查通过。
2026-09-10 17:01:39 +08:00

69 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 失败提醒能力 CP1 交接
## 已完成的产品行为
- 内部收到明确的最终技术失败后,登记一条包含酒店、邮件标题、失败阶段、简短原因和处理记录编号的提醒。
- 同酒店、同次处理的重复失败只保留第一条提醒;后续阶段的连锁错误不会生成另一条。
- 未完成处理、正常待确认/补充/人工办理和成功结果不会登记失败提醒。
- 发送结果分别保留待发送、已受理、配置暂停、结果不确定和安全重试耗尽;不会改变或重跑原邮件。
- 请求确定没有发出时自动有限重试。已受理、发送后超时/断流、发送时进程退出等情况不能盲目重发。
- 配置修正后,内部重试入口只恢复那条提醒。已受理或结果不确定不能通过普通重试入口重发。
本次只做好独立能力。邮件流程的自动失败判断与触发尚未接线,当前服务未加载本次构建,也没有真实发送。
## 内部接线位置
- `platform.notification.service.FailureNotificationService.register` 是唯一内部登记入口,无HTTP Controller;调用方在原结果提交后传入 `FailureNotificationRequest`。
- `AutomaticProcessingOutcome.FINAL_TECHNICAL_FAILURE` 才入队,其余结果直接返回空。该字段是调用方提供的可信事实,本模块不从人工任务类型、页面颜色或历史错误猜测最终失败。
- `executionIdentity` 必须是同一次处理的稳定身份;已有run使用其run ID。缺run的入口失败使用稳定的那次来源执行身份,后续关联补全不得换去重身份。无run到run的桥接由CP2完成。
- `recordId` 使用已有 `source-<id>` 或 `replay-<id>`。酒店名与标题由可信来源读取;原因只能选择固定安全枚举,禁止传原始异常/邮件正文/Agent回答。
- `find(hotelId, notificationId)` 与 `retry(hotelId, notificationId)` 为内部查询与恢复,不新建员工页面、不开放匿名或调试写接口。
- 登记最终失败和运行发送worker都拒绝原业务事务仍打开的情况,避免事务后来回滚却先发送提醒,或网络等待占用原任务事务。
CP2必须补齐原方案列明的普通工作台失败漏判、Layer6有界恢复、Booking技术失败转人工漏判,并核对已提交工作台receipt。CP1不能替代这些全链验收。
## 持久与并发边界
平台库新增 `V39__create_failure_notification_outbox.sql`,表为 `platform_failure_notification_outbox`;没有修改Booking PostgreSQL或既有业务表。唯一键为酒店ID与 `SHA256(hotelId + 换行 + executionIdentity + 换行 + FINAL_FAILURE)`,不含阶段、原因或当前时间。首次内容冻结。
仓储明确注入平台 `dataSource`;使用平台短独立事务保存领取、发送开始及完成。状态迁移为:
```text
READY/RETRY_WAIT → CLAIMED → SENDING → ACCEPTED
→ RETRY_WAIT / FAILED_RETRYABLE
→ PAUSED_CONFIGURATION
→ UNKNOWN
```
- 只有当前随机lease token且未过期的持有人能开始发送和写结果。
- CLAIMED过期恢复READY;SENDING过期转UNKNOWN,避免进程退出后重复发送。
- 累计开始发送次数永久保留。自动重试最多5次,退避从30秒开始;耗尽后内部人工恢复允许再尝试,但不重置累计次数。
- 配置暂停/安全重试耗尽可恢复同一记录;UNKNOWN/ACCEPTED不可恢复为待发送。
- 发送使用专属daemon线程,30秒轮询,不占用或替换其他模块的Spring TaskScheduler;关闭应用时中断该线程。
## 配置与外部协议
默认读取工作目录 `.env.failure-notification`;从server目录运行时可回退到父目录同名文件。其他运行目录用 `notification.failure.config-file` 指定绝对路径。显式路径不存在不回退到其他配置。
只解析四个已声明配置键,支持简单单/双引号,拒绝重复/未知键和命令插值,不执行shell。每次检查/发送重新读取,Secret不进入公共配置集合、toString、日志或通知表。
- `FAILURE_NOTIFICATION_ENABLED=false`:默认关闭;无文件也关闭。
- `WEBHOOK_EXTERNAL_TOKEN`:32字符原始凭证,真实值只在私有文件中。
- `WEBHOOK_CONFIG_ID='9998'`:严格使用本轮目标,不接受资料示例9999。
- `WEBHOOK_SEND_URL`:确认后的完整HTTPS URL,不接受用户名密码、query或fragment。本机HTTP只通过包内测试构造提供,无生产放宽开关。
微信端使用单次POST,JSON仅 `id/content`,原始Token放 `x-token`。连接最长5秒,总请求含响应正文最长15秒;响应最多16KiB,关闭重定向,一次性请求正文拒绝底层再次发送。只有HTTP200、整数code=0、布尔data=true才记“已受理”。200不证明微信送达;5xx、非约定响应、断流/超时一律保留不确定,不假定请求未发出。
API目前没有接收端幂等键、受理查询或回调,因此不能宣称远端恰好送达一次。真实地址、服务端部署及ID9998目标仍待真实联调确认。文档候选为 `https://biz.nianxx.cn/wechat/webhookInfo/sendMessageByOut`,本次未请求该地址。
## 验收与上线状态
已在隔离源码副本使用合成邮件标题、合成Token、H2内存数据库与本机HTTP模拟服务检查;没有复制真实私有配置、重启当前服务或运行真实邮件。
加载本次构建时会执行新增平台表迁移;当前只交付源码,当前运行数据尚未执行该迁移。配置仍关闭,CP2衔接和真实联调前不启用。关闭通知不会影响原邮件处理与人工确认。
## 2026-09-10 统一加载附记
CP1通知组件/V39和CP2a失败收尾/PG V21已与最新C1及历史保留共同加载当前本地后台;发送关闭,未接自动失败发现/登记,未发送或补发。当前业务数据保留。见[实际运行证据](../../../.project-docs/50-evidence/topics/2026-09-10-unified-runtime-load.md)。