fix(wle): 超时参数真正生效 —— 售后拦截 20s 不重试、表级探测走 querySlow #98
Loading…
x
Reference in New Issue
Block a user
No description provided.
Delete Branch "yanhui-wle-timeout-fix-1114"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景
11-13 09:10 那轮「仓储物流转运异常」钉钉推送没发出去。查下来不是 webhook 问题,是业务库查询超时:
system_config记录:lastSentDate=2026-11-12、lastFailedAt=2026-11-13T01:30:07Z、lastError=Timeout ... 300000ms。排查时发现代码里还有两笔纯粹的白等,跟「业务库变慢」叠加在一起把 300s 撑爆了。
改动
1.
timeoutMs是无效参数 —— 加告警,别再静默吞cloudDatabase只读connectRequestTimeoutMs/requestTimeout。mssql 12.x 上请求级request.timeout不生效,超时只能靠池配置级requestTimeout,而共享池(query())的池级超时在 pool 创建时就定死了 —— 调用方改不了。所以服务层原来写的
{ timeoutMs: 240000 }(想着「给足 4 分钟」)从来没生效过,实际一路按 60s(普通query())/ 300s(querySlow)掐。→
query()/queryWithFreshConnection()入口加warnLegacyTimeoutOption():再传timeoutMs就打日志,不再当没看见。2. 售后拦截子查询:名义 240s → 真 20s,且不重试
两张售后表在 rpt 副本里是堆表(零索引),实测 125 万行 4.5s / 176 万行 8.5s。原来超时后
query()还把它当可重试错误 ——resetPool()+ 重查一次,白等 60s(11-13 日志里约 2 分钟)。改成:
售后表跟不上时业务影响只是「少剔几单」(
catch里本来就有降级),不值得为它把整批核验拖进超时窗口。3. 空窗口的表级
MAX(query_time)探测也改走querySlow全表 MAX 实测已经从记忆里的 13.5s 退化到 60s 以上,用共享池等于永远探测不到 →
sourceLastUpdate恒空 → 又分不清「0 单是没发货还是没同步」(PR #94 那个场景)。→
querySlow+connectRequestTimeoutMs=180000+maxAttempts=1(探测失败只需退回「不知道」,重试只是把等待翻倍)。可用CANGKU_WLE_SOURCE_LAST_UPDATE_TIMEOUT_MS覆盖。4. 顺手修一个时间炸弹测试
用例「窗口 0 行但数据源是新的」硬编码
sourceMaxQueryTime = '2026-11-02 09:58:00',而服务层算ageMinutes用的是真实时钟(registry.beijingNow()),不是测试传进来的now—— 隔一天就变成「停更 24h」,该用例从 11-03 起在main上一直是红的。改成相对当前时间。验证
新增 2 条断言,直接锁住「超时参数必须真生效」:
api === 'querySlow'、connectRequestTimeoutMs === 20000、maxAttempts === 1、timeoutMs === undefinedapi === 'querySlow'、connectRequestTimeoutMs >= 120000、maxAttempts === 1、timeoutMs === undefinednpm --prefix backend run check:505/507。两个失败都是环境原因,与本改动无关:负缓存带 TTL—— 本机没起13333 → 218.93.9.21:1433隧道,连不上业务库secret backup ... owner-only permissions—— Windows 上chmod不生效(期望 0600 / 实际 0666)不解决什么
业务库整体变慢(今天
SELECT 1要 1.5s、TOP 1订单表 3.6s)是数据库侧的事,代码改不了,需要 IT 看索引/统计信息/负载。本 PR 只保证「不那么容易被自己拖超时」,真正的超时兜底还是靠 #96 的重试窗口。11-13 09:10 那轮钉钉推送 300s 超时没发出去。除了业务库本身变慢,代码里还有两笔白等: 1. `{ timeoutMs: 240000 }` 是无效参数 cloudDatabase 只读 connectRequestTimeoutMs / requestTimeout。mssql 12.x 上请求级 request.timeout 不生效,超时只能靠池配置级 requestTimeout,而共享池(query())的 池级超时在 pool 创建时就定死 —— 所以「给足 4 分钟」从来没生效过,实际一路按 60s(普通 query)/ 300s(querySlow)掐断。 → cloudDatabase 两个查询入口加 warnLegacyTimeoutOption():再传 timeoutMs 就告警, 不再静默当没看见。 2. 售后拦截子查询:名义 240s → 真 20s,且不重试 两张售后表在 rpt 副本里是堆表,实测 4.5s / 8.5s。原来超时后 query() 还把它当 可重试错误 resetPool + 重查一次,白等 60s(11-13 日志里约 2 分钟)。 改成 querySlow + connectRequestTimeoutMs=20000 + maxAttempts=1:超了就按既有 catch 降级「不剔除」,不为一个补充判据把整批核验拖进超时窗口。 3. 空窗口的表级 MAX(query_time) 探测改走 querySlow(180s,maxAttempts=1) 全表 MAX 实测已跑不进 60s,用共享池等于永远探测不到 → sourceLastUpdate 恒空, 「0 单是没发货还是没同步」又分不清了。探测失败只需退回「不知道」,不值得重试。 顺带修一个时间炸弹测试:用例「窗口 0 行但数据源是新的」硬编码 sourceMaxQueryTime 为 2026-11-02 09:58,而服务层算 ageMinutes 用的是真实时钟(registry.beijingNow)—— 隔一天就变成「停更 24h」,该用例在 origin/main 上从 11-03 起一直是红的。 改成相对当前时间。 测试:warehouseLogisticsException 36/36 通过(新增 2 条「超时参数必须真生效」断言)。