專案

一般

配置概況

動作

Bug #1519

進行中

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

[Backend Bug][#1518-R1] Connector 快照跨事件來源失序,停止後可能回退為充電中

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

狀態:
In Progress
優先權:
High
被分派者:
-
開始日期:
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 指示不得部署或重啟案場服務

問題

MeterValues 背景 dispatcher 與 StopTransaction、StatusNotification、StartTransaction 等 Connector 狀態事件使用不同發布路徑,沒有共用同一個 per-connector 順序或 authoritative state version。

可能順序:

  1. MeterValues 背景工作先讀到 Connector 仍為充電中。
  2. StopTransaction 提交,Branch 先發布已停止快照。
  3. 前面的 MeterValues 工作較晚完成,卻發布先前讀到的充電中快照。
  4. HQ/Admin/LIFF 直接合併後到的資料,畫面可能回退為充電中。

目前 event timestamp 是發布當下時間,舊狀態晚送時反而會取得較新的 timestamp,因此接收端無法用現有時間欄位辨識。

影響

  • 使用者已停止充電後,畫面可能再次顯示充電中。
  • currentTransactionId、driverState、可用操作或即時數值可能被舊快照帶回。
  • 若前一交易的背景工作晚到,也可能干擾下一筆交易畫面。

相關程式

  • java/ems_branch/.../MeterValueConnectorEventDispatcher.java
  • java/ems_branch/.../TransactionService.java
  • java/ems_branch/.../StatusNotificationHandler.java
  • java/ems_branch/.../ConnectorEventPublisher.java
  • java/ems_hq/.../ConnectorEventSubscriber.java
  • react/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 的同步路徑。

驗收條件

  1. 用 barrier/latch 讓 MeterValues 工作停在已讀取舊狀態、尚未發布,再完成 StopTransaction;放行後最終畫面仍為已停止。
  2. StartTransaction、StopTransaction、StatusNotification 與 MeterValues 同 Connector 交錯時,最終快照一律與資料庫 authoritative state 相同。
  3. 舊事件不能覆蓋較新的 currentTransactionId、driverState 或可用操作。
  4. 不同 Connector 可並行處理,同一 Connector 必須保序。
  5. 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 尚未執行。

是由 陳國瑋 於 3 天 前更新

  • 狀態 從 New 變更為 In Progress

R1 已開始實作;目前完成 Branch 共用 Connector 發布邊界與隔離單元案例,Ken environment 整合/E2E 尚待依測試計畫啟動。

動作

匯出至 Atom PDF