|
|
@@ -187,13 +187,15 @@ class HarCallbackServiceTest {
|
|
|
*
|
|
|
* 【为什么五个要素全钉】状态字面量、计数上界、排序方向、LIMIT 任一写错,症状都是
|
|
|
* 「失败回调永远不被重试而套件全绿」—— 没有别的任务会断言这个查询。
|
|
|
- * 【取值为什么定 3 而不是默认 8】钉住上界来自 HarProperties 而不是写死的数字。
|
|
|
+ * 【取值为什么定 5 而不是默认 3】钉住上界来自 HarProperties 而不是写死的数字 ——
|
|
|
+ * 自定义值必须**≠ 默认值**:定成默认值的话,「写死默认常量」的回归照样能过(本用例
|
|
|
+ * 原定 3、恰逢 2026-10-09 默认从 8 收紧到 3,判别力归零,故改为 5)。
|
|
|
* 【断言为什么分两半】MyBatis-Plus 的 .eq()/.lt() 不把值写进 SQL 文本(塞进
|
|
|
* paramNameValuePairs)⇒ 结构看 getSqlSegment(),取值看参数表,取值用**恰好相等**。
|
|
|
*/
|
|
|
@Test
|
|
|
void retryFailed_pinsScanQuery() {
|
|
|
- props.setCallbackMaxRetries(3);
|
|
|
+ props.setCallbackMaxRetries(5);
|
|
|
when(orderMapper.selectList(any())).thenReturn(List.of());
|
|
|
|
|
|
service.retryFailed();
|
|
|
@@ -203,7 +205,7 @@ class HarCallbackServiceTest {
|
|
|
LambdaQueryWrapper<?> w = scan.getValue();
|
|
|
String sql = w.getSqlSegment();
|
|
|
|
|
|
- assertEquals(Set.of(HarNotifyStatus.FAILED, 3), new HashSet<>(w.getParamNameValuePairs().values()),
|
|
|
+ assertEquals(Set.of(HarNotifyStatus.FAILED, 5), new HashSet<>(w.getParamNameValuePairs().values()),
|
|
|
"取值必须恰好是 {FAILED, 上限},实测: " + w.getParamNameValuePairs());
|
|
|
assertTrue(sql.contains("notify_status = #{"),
|
|
|
"必须按 notify_status 等值过滤,实测: " + sql);
|
|
|
@@ -272,8 +274,9 @@ class HarCallbackServiceTest {
|
|
|
*
|
|
|
* <p>封顶那句(存量不补推)是**用户裁定**的落地处:执行那一刻已有的 FAILED 单
|
|
|
* 不能因为新列默认 0 被当成「没试满」全部补推。删掉它、或把上限值改得与
|
|
|
- * {@code har.callback-max-retries} 不一致(默认 8,生产配得比 8 大时脚本要同步改),
|
|
|
- * 部署时就会把存量积压重推一轮 —— 而套件除了本用例没有任何红点。
|
|
|
+ * {@code har.callback-max-retries} 的默认值不一致(现为 3,2026-10-09 用户裁定
|
|
|
+ * 从 8 收紧;生产把运行时上限配得比脚本封顶值大时脚本要同步改),部署时就会
|
|
|
+ * 把存量积压重推一轮 —— 而套件除了本用例没有任何红点。
|
|
|
*/
|
|
|
@Test
|
|
|
void schemaScript_addsRetryColumnsAndSealsExistingFailedRows() throws Exception {
|
|
|
@@ -285,9 +288,18 @@ class HarCallbackServiceTest {
|
|
|
"notify_count 列不见了 —— 每次回调尝试都写它(SQL 侧自增),缺列即每次写库抛错");
|
|
|
assertTrue(text.matches("(?s).*ALTER TABLE pay_har_order ADD COLUMN IF NOT EXISTS last_notify_time timestamp.*"),
|
|
|
"last_notify_time 列不见了 —— 重试扫描的排序键,缺列即重试扫描每分钟抛一次错");
|
|
|
- assertTrue(text.matches("(?s).*UPDATE pay_har_order SET notify_count = 8 WHERE notify_status = 'FAILED' AND notify_count = 0.*"),
|
|
|
+ Matcher seal = Pattern.compile(
|
|
|
+ "UPDATE pay_har_order SET notify_count = (\\d+) WHERE notify_status = 'FAILED' AND notify_count = 0")
|
|
|
+ .matcher(text);
|
|
|
+ assertTrue(seal.find(),
|
|
|
"存量 FAILED 行的封顶句不见了/被改了 —— 「存量不补推」是 2026-10-09 的用户裁定:"
|
|
|
- + "新列默认 0 会让存量失败单立刻被当成「没试满」全部重推。值必须 = har.callback-max-retries(默认 8)");
|
|
|
+ + "新列默认 0 会让存量失败单立刻被当成「没试满」全部重推");
|
|
|
+ int sealedTo = Integer.parseInt(seal.group(1));
|
|
|
+ assertEquals(new HarProperties().getCallbackMaxRetries(), sealedTo,
|
|
|
+ "封顶值必须 = har.callback-max-retries 的默认值 —— 脚本与代码必须同步改:"
|
|
|
+ + "脚本值 < 运行时上限 ⇒ 存量被当成「没试满」补推;改代码忘改脚本的漂移由本断言拦下");
|
|
|
+ assertEquals(3, sealedTo,
|
|
|
+ "2026-10-09 用户裁定:回调失败最多尝试 3 次(含首推)—— 封顶值随默认值从 8 收紧到 3");
|
|
|
assertTrue(text.matches("(?s).*CREATE INDEX IF NOT EXISTS idx_har_order_callback_retry\\s+ON pay_har_order \\(last_notify_time\\) WHERE notify_status = 'FAILED'.*"),
|
|
|
"重试扫描的部分索引不见了 —— 该查询唯一的热路径(谓词 + 排序键一个索引全包)");
|
|
|
}
|