Bug #1519
進行中Bug #1518: [Backend Bug] StopTransaction 補送失敗後保留殭屍交易,Connector 無法再次充電
[Backend Bug][#1518-R1] Connector 快照跨事件來源失序,停止後可能回退為充電中
概述
背景¶
本票是 #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 指示不得部署或重啟案場服務
問題¶
MeterValues 背景 dispatcher 與 StopTransaction、StatusNotification、StartTransaction 等 Connector 狀態事件使用不同發布路徑,沒有共用同一個 per-connector 順序或 authoritative state version。
可能順序:
- MeterValues 背景工作先讀到 Connector 仍為充電中。
- StopTransaction 提交,Branch 先發布已停止快照。
- 前面的 MeterValues 工作較晚完成,卻發布先前讀到的充電中快照。
- HQ/Admin/LIFF 直接合併後到的資料,畫面可能回退為充電中。
目前 event timestamp 是發布當下時間,舊狀態晚送時反而會取得較新的 timestamp,因此接收端無法用現有時間欄位辨識。
影響¶
- 使用者已停止充電後,畫面可能再次顯示充電中。
- currentTransactionId、driverState、可用操作或即時數值可能被舊快照帶回。
- 若前一交易的背景工作晚到,也可能干擾下一筆交易畫面。
相關程式¶
java/ems_branch/.../MeterValueConnectorEventDispatcher.javajava/ems_branch/.../TransactionService.javajava/ems_branch/.../StatusNotificationHandler.javajava/ems_branch/.../ConnectorEventPublisher.javajava/ems_hq/.../ConnectorEventSubscriber.javareact/web/app/charger/store/useChargingStore.ts
建議修正¶
- MeterValues、Start/StopTransaction、StatusNotification 等 commit-after 更新共用同一套 per-connector 發布序列。
- 背景工作只傳遞 ID/變更通知,輪到發布時重新讀取 authoritative state。
- 發布期間若收到新變更,完成本次後必須再重新載入及發布,確保最終狀態正確。
- 增加單調遞增的 state version;HQ、Admin 與 LIFF 必須忽略版本較舊的事件。
- 不得把 Connector event 再移回 OCPP CALLRESULT 的同步路徑。
驗收條件¶
- 用 barrier/latch 讓 MeterValues 工作停在已讀取舊狀態、尚未發布,再完成 StopTransaction;放行後最終畫面仍為已停止。
- StartTransaction、StopTransaction、StatusNotification 與 MeterValues 同 Connector 交錯時,最終快照一律與資料庫 authoritative state 相同。
- 舊事件不能覆蓋較新的 currentTransactionId、driverState 或可用操作。
- 不同 Connector 可並行處理,同一 Connector 必須保序。
- OCPP MeterValues CALLRESULT 快速路徑不可因此重新被背景 snapshot 阻塞。
證據狀態¶
本項由完整發布路徑與併發順序分析確認,尚未執行 RabbitMQ/現場 E2E;修正時必須補正式可控制時序的 regression test。
是由 陳國瑋 於 3 天 前更新
#1519 R1 實作範圍與測試環境確認(2026-09-28)¶
Ken 確認:現在與未來,每個案場只有一個 Branch;一個 Branch 就是一個案場。 R1 因此以單一 Branch 的 per-Connector 發布邊界為設計前提。原 description 的「單調 state version+各接收端丟棄舊版」是審查時提出的建議方案;本次先採共用發布邊界、在取得 Connector 序列鎖後重新讀取 authoritative DB snapshot,避免已讀到舊狀態的 MeterValues 在 StopTransaction/StatusNotification 新狀態後才送出。一般業務事件先排入背景,不讓 OCPP CALLRESULT 等待 RabbitMQ/Admin WebSocket。若 Ken environment E2E 發現跨 transport 或重連時仍有逆序,需在結案前補強,不能僅憑單元測試宣稱完成。
測試目標環境是 Ken environment;需真實充電行為時請 Ken 手動進行。不得在 A17 有車充電期間為本票重啟或注入競態。詳細 E2E 步驟記錄於 documents/20260928/redmine-1519-ken-e2e-plan.md,案例目錄新增 CHG-049(P1)。目前只有隔離單元案例及跳過測試的編譯完成;RabbitMQ/HQ/LIFF/Admin 的整合與 Ken environment E2E 尚未執行。