Skip to content

fix(app): WS 重連後沒有人對帳——司機繼續開往已取消的行程(第二十九輪) - #101

Merged
thothawei merged 1 commit into
mainfrom
claude/round29-ws-reconnect
Aug 1, 2026
Merged

fix(app): WS 重連後沒有人對帳——司機繼續開往已取消的行程(第二十九輪)#101
thothawei merged 1 commit into
mainfrom
claude/round29-ws-reconnect

Conversation

@thothawei

Copy link
Copy Markdown
Owner

上一輪列的兩個候選,查下去發現是同一個洞的兩半

⚠️ 先更正我上一輪寫錯的一句話

第二十八輪的「同族還沒碰的角落」寫著:「司機端在待命時輪詢(hero 上線後持續回報位置並對帳),情境不同。未查證」。

實查是錯的grep Timer lib/driver/driver_controller.dart 只有 _locationHealthTimer(定位健康度重評),司機端沒有任何行程輪詢_api.activeRide() 只在三種時機被呼叫:init()、自己動作之後(接單/上車/完成)、onAppResumed

而且因為這句話錯了,我上一輪把司機端評成「情境不同、可以晚點看」——實際上它是兩端裡最嚴重的一邊。 TODO 已當場更正。

根因一句話

onConnectionChanged 只記旗標、notifyListeners,沒有人去問後端;而 WS 重連不補送斷線期間的事件(第四輪就記過)。兩件事湊起來,斷線視窗裡發生的每一件事都永遠送不到。

為什麼司機端最嚴重

斷線視窗的補救 結果
乘客端 有進行中訂單時每 15 秒輪詢 有訂單時會自己校正;閒置時輪詢是停著的(第二十八輪那個情境剛好落在這裡)
司機端 沒有任何行程輪詢 只剩 onAppResumed——而那需要 App 真的進過背景。開車時 App 全程在前景,走不到

最惡劣的具體後果:斷線視窗裡乘客取消 → ride.cancelled 送不到 → 司機繼續開往一個已經取消的上車點,而畫面上那張行程卡看起來完全正常。

修法(兩端同一招)

onConnectionChanged重連時補一次對帳:司機端 _restoreActiveRide(silent: true)、乘客端 refreshActive(silent: true)

  • 只在「重連」時做,第一次連上不做(新增 _everConnected 旗標)——冷啟動時 init() 才剛問過,再問只是多打一支 API。
  • 斷線本身不觸發(問了也問不到)。
  • 兩端都走 silent:這不是使用者按出來的,失敗不該冒錯誤橫幅。

驗收

  • flutter analyze 無 issue、flutter test 448 passed(444 +新 4)、58 個測試檔。
  • 先紅再修:司機端主案在修改前就是紅的(activeCalls 停在 1)。
  • 反向驗證三處:拿掉司機端對帳 → 主案 FAIL;拿掉 _everConnected 守衛 → 「第一次連上不重複對帳」FAIL(變成 2 次);拿掉乘客端對帳 → 乘客端那案 FAIL
  • flutter build apk --debug --flavor customer -t lib/main_customer.dart 成功。

過程中修正的一個測試錯誤

第一版司機端測試跳過了「第一次連上」,於是 _everConnected 永遠是 false、重連判定不成立,測試紅得像是修法沒生效。錯的是測試不是程式——production 一定會先連上一次。已補上初次連線。與上一輪同一個教訓:測試紅了要先問「是我的假設錯了嗎」

誠實說明補不到的缺口

弱網下根本沒有「重連」事件:凍結的後端不會送 FIN,onConnectionChanged 永遠不會 false→true,本輪的對帳幫不上忙。要修得靠心跳逾時主動斷線重連,動的是 FleetWsClient——已列為下一輪的首選候選。

開工前的例行實查(第十二次)

三個外部卡點依然都不在;開工時三個 repo 的 open PR 皆為 0。

🤖 Generated with Claude Code

上一輪列的兩個候選查下去是同一個洞的兩半,而且**我上一輪寫的一句話是錯的**:
第二十八輪的「同族還沒碰的角落」寫著「司機端待命時有輪詢」。實查是錯的——
grep Timer 只有 _locationHealthTimer(定位健康度),司機端**沒有任何行程輪詢**。
已在 TODO 當場更正。

根因:onConnectionChanged 只記旗標、notifyListeners,沒有人去問後端;而 WS 重連
不補送斷線期間的事件(第四輪就記過)。兩件事湊起來,斷線視窗裡發生的每一件事
都永遠送不到。

司機端最嚴重:乘客端至少在有進行中訂單時每 15 秒輪詢會校正,司機端只剩
onAppResumed——而那需要 App 真的進過背景,開車時 App 全程在前景,走不到。
最惡劣的具體後果:斷線視窗裡乘客取消 → ride.cancelled 送不到 → 司機繼續開往
一個已經取消的上車點,而畫面上那張行程卡看起來完全正常。

修法兩端同一招:onConnectionChanged 在**重連**時補一次對帳(司機
_restoreActiveRide、乘客 refreshActive,都走 silent)。只在重連時做、第一次連上
不做(新增 _everConnected 旗標;冷啟動時 init 才剛問過);斷線本身不觸發。

驗收:flutter analyze 無 issue、flutter test 448 passed(444+新 4)、58 個測試檔、
flutter build apk --debug --flavor customer 成功。司機端主案在修改前就是紅的。
反向驗證三處:拿掉司機端對帳 → 主案 FAIL;拿掉 _everConnected 守衛 → 「第一次
連上不重複對帳」FAIL;拿掉乘客端對帳 → 乘客端那案 FAIL。

過程中修正一個測試錯誤:第一版司機端測試跳過了「第一次連上」,_everConnected
永遠 false,測試紅得像是修法沒生效——錯的是測試不是程式,production 一定會先
連上一次。與上一輪同一個教訓:測試紅了要先問「是我的假設錯了嗎」。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@thothawei
thothawei merged commit 03b3c77 into main Aug 1, 2026
2 checks passed
@thothawei
thothawei deleted the claude/round29-ws-reconnect branch August 1, 2026 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant