動作
Bug #1522
進行中Bug #1518: [Backend Bug] StopTransaction 補送失敗後保留殭屍交易,Connector 無法再次充電
[Backend Bug][#1518-R4] Connector dispatcher pending 競爭造成更新靜默遺失
狀態:
New
優先權:
Normal
被分派者:
-
開始日期:
2026-09-28
完成日期:
預估工時:
概述
背景¶
本票是 #1518 的子票,來源為 2026-09-28 對 MeterValues 第二~第五階段實作的 Astra 程式審查。該實作目前只存在主要 workspace,尚未部署至 A17;A17 已套用的第一階段複合索引不受本票影響。
工作位置:
- EMS workspace:
/Users/ken/Documents/workspace/workspace_cloudlink/ems - EMS branch:
feature/redmine-1517-ocpp-liveness -
java/charge_point為獨立 repository,使用相同 branch 名稱 - 直接使用主要 workspace,不建立 worktree
- 未經 Ken 指示不得部署或重啟案場服務
問題¶
MeterValueConnectorEventDispatcher.enqueue() 先從 map 取得 pending,再進入 pending 的 synchronized block。兩步之間,舊 dispatch 可能成功完成並從 map 移除該 pending。
新的 enqueue 隨後仍更新及排程已被移除的舊物件;task 執行時發現 map 已不再指向該 pending,直接退出。此情況不會發布、重試或告警,屬於靜默漏送。
審查已用可控制 monitor 的案例穩定重現:排程建立兩次,實際只發布一次。
影響¶
- Connector 最新即時指標可能沒有推送至 HQ/Admin。
- 如果後續沒有新事件,畫面會持續停留在舊資料。
- 同一競爭可能出現在成功移除及達重試上限移除附近。
相關程式¶
java/ems_branch/.../MeterValueConnectorEventDispatcher.java
建議修正¶
- 取得 pending monitor 後重新驗證
pendingByConnector.get(connectorId) == pending;若已失效,重新取得目前 pending。 - pending 增加 closed/generation 狀態,移除前在鎖內關閉。
- map membership、version 更新及 pending lifecycle 必須一起原子管理;可使用 retry loop 或
ConcurrentHashMap.compute()。 - 不可單純刪掉 version 檢查,否則舊 task 可能反向覆蓋新 task。
- 與 #1518-R1 的 per-connector 發布順序一起設計,避免分別修正後仍有跨來源失序。
驗收條件¶
- 審查中的 enqueue-race 案例由發布 1 次恢復為預期 2 次。
- 覆蓋成功發布移除、失敗重試、達上限移除及 publish 中收到新 request。
- 同 Connector 維持合併、保序與最大等待時間;不同 Connector 可並行。
- 任何已接受的 refresh 不得無 log 地消失。
- 測試使用 barrier/latch 控制交錯,不依賴隨機執行或長時間 sleep。
重現¶
python3 test_report/evidence/1518-review/run_one.py enqueue-race
審查時 scheduled=2、expected published=2、actual=1。
沒有任何資料可供顯示
動作