| New file |
| | |
| | | # 01 — 交易确认补偿被测试库里累计的遗留行挤满,用例恒失败 |
| | | |
| | | 状态:**仅排查,未改动**。现象出在交易确认补偿(属支付链路),按仓库约定整理后交接,未动代码与测试数据。 |
| | | |
| | | ## 现象 |
| | | |
| | | `docs/agents/testing.md` 记录的 3 项基线失败之外,多出一项: |
| | | |
| | | ``` |
| | | PaymentFundConfirmationTests.aPendingConfirmationOfAVerifiedOrderIsRetriedWithoutAnotherVerification:173 |
| | | expected: "confirmed" |
| | | but was: "pending" |
| | | ``` |
| | | |
| | | 2026-09-17 全量跑(319 项)时出现;单独跑这个类(21 项)同样失败——**确定性失败,不是偶发**。 |
| | | |
| | | ## 根因 |
| | | |
| | | 补偿任务扫「已核销 + 待确认」订单时是**全库扫描 + limit**: |
| | | |
| | | `PaymentFundConfirmationRetry.java:54-64` |
| | | |
| | | ```sql |
| | | select distinct o.id as order_id |
| | | from benefit_order o join payment_transaction p on p.order_id = o.id |
| | | where o.deleted = 0 and o.order_status = 1 and o.verify_status = 1 and o.refund_status = 0 |
| | | and p.status = 'SUCCEEDED' and p.funds_confirmation_status in ('pending', 'confirming') |
| | | order by o.id asc |
| | | limit ? |
| | | ``` |
| | | |
| | | 用例传的是 `retry(50)`(`PaymentFundConfirmationTests.java:172`),而它自己那单是**新建**的(id 最大), |
| | | 排在 `order by o.id asc` 的最后。测试库是共享且从不清理的,符合条件的遗留行一旦累计到 50 条以上, |
| | | 用例这单就永远轮不到 → 状态停在 `pending`。 |
| | | |
| | | ## 证据(2026-09-17 13:1x 对 `talent_card_test` 实测) |
| | | |
| | | ``` |
| | | eligible=60 oldestId=906 newestId=6549 firstSeen=2026-09-14 12:18:17 |
| | | benefit_order total=6543 |
| | | payment_transaction: pending=242 confirming=113 confirmed=506 reverting=44 |
| | | ``` |
| | | |
| | | - 符合扫描条件的行 **60 条 > limit 50**;最早的一条是 **09-14** 留下的,早于本轮任何改动。 |
| | | - `newestId=6549` 正是该用例自己刚插入的那单——它在 60 条里排最后,被 limit 截掉。 |
| | | - 这些行不会被排空:被处理过的行大多落在 `confirming`(在扫描条件内),所以每轮都会重新占住名额, |
| | | 集合是**饱和**的——也就是说,这个用例从今往后每跑必红,直到有人清理或改用例。 |
| | | - 无关本轮工作:本轮只改了 `merchant_onboarding_application` 相关读取 |
| | | (`MerchantPaymentReadinessService`、`MerchantOnboardingProgressService`), |
| | | 新用例也没有插入 `benefit_order`/`payment_transaction`。 |
| | | |
| | | 旁证:同文件相邻用例的注释已经写明这个危险——「补偿任务扫的是整库,会顺带处理其它用例留下的 |
| | | 「已核销 + 待确认」订单」(`PaymentFundConfirmationTests.java` 中 `theRetrySkipsOrdersWhoseFundsAreAlreadyConfirmed`)。 |
| | | |
| | | ## 建议改法(二选一,请不要只做第二个) |
| | | |
| | | 1. **让用例自己把窗口腾出来**(推荐,`docs/agents/testing.md`「测试库的状态是共享的」给的就是这个办法): |
| | | 在用例准备阶段,把本次之外的符合条件行挪出时间窗口/状态窗口(例如把它们置成 `confirmed`, |
| | | 或按 id 条件排除),再断言本单。这样不再依赖"库里符合条件的行少于 50"这个未被写下来的前提。 |
| | | 2. **清理测试库遗留**(只能缓解,不能治本):把 50 条老行处理掉,例如 |
| | | `update payment_transaction set funds_confirmation_status='confirmed' where order_id in (...)`, |
| | | 或干脆 `scripts/reset-test-db.ps1` 重建——注意它是共享库,跑之前要确认没有别的会话在跑测试。 |
| | | 不改用例的话,累计到 50 条以上还会复发。 |
| | | |
| | | 也建议把这条顺手写进 `docs/agents/testing.md` 的已知失败表,说明它是环境相关、可自愈的那一类。 |
| | | |
| | | ## Comments |
| | | |
| | | - 2026-09-17 由商户端「收款能力」那一轮的实现会话发现并留档。**没有**改这个用例、**没有**动测试库数据: |
| | | 两者都在支付链路范围内,按 `AGENTS.md` 的按域分工只做只读排查后交接。排查期间的本地全量结果为 |
| | | 「319 项,2 failures / 2 errors = 上述 1 项 + `docs/agents/testing.md` 记录的 3 项基线」。 |