專案

一般

配置概況

動作

Bug #1522

進行中

Bug #1518: [Backend Bug] StopTransaction 補送失敗後保留殭屍交易,Connector 無法再次充電

[Backend Bug][#1518-R4] Connector dispatcher pending 競爭造成更新靜默遺失

是由 陳國瑋 於 3 天 前加入.

狀態:
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 發布順序一起設計,避免分別修正後仍有跨來源失序。

驗收條件

  1. 審查中的 enqueue-race 案例由發布 1 次恢復為預期 2 次。
  2. 覆蓋成功發布移除、失敗重試、達上限移除及 publish 中收到新 request。
  3. 同 Connector 維持合併、保序與最大等待時間;不同 Connector 可並行。
  4. 任何已接受的 refresh 不得無 log 地消失。
  5. 測試使用 barrier/latch 控制交錯,不依賴隨機執行或長時間 sleep。

重現

python3 test_report/evidence/1518-review/run_one.py enqueue-race

審查時 scheduled=2、expected published=2、actual=1。

沒有任何資料可供顯示

動作

匯出至 Atom PDF