fix(app): 「我的行程」只看得到最近 20 趟——舊行程的協尋與補評分入口整個消失(第二十四輪) - #97
Conversation
`fetchRideHistory()` 固定要 20 筆、畫面沒有載入更多,而這個畫面是事後聯絡司機、 申報遺失物、補評分的唯一入口——第 21 趟以前的行程在乘客端永遠打不開。 後端 `limit` 照單全收(上限 5000),所以本輪不動 dispatch:改成捲到底自動再要一頁 (沒有 cursor,就是把 limit 加大重讀)。載入更多的錯誤與整頁錯誤分開、失敗時視窗 不推進;下拉刷新保持已展開的筆數,登出才收回一頁。 驗收:flutter analyze 無 issue、flutter test 386 passed;反向驗證兩半各紅一次; 模擬器實跑 25 筆行程,修好的版本捲到底發出 LIMIT 40 並撈到最舊那筆, 修改前的版本只發過一次 LIMIT 20、停在第 20 筆。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1. 造大量測試行程改用 tool/seed_customer_rides.sh:叫車限流(5 次/分)、 「已有進行中訂單」、建單回應是 ride_id 不是 id——三個都不會讓迴圈停下來, 自己寫 for 迴圈會整批靜默失敗還印得像成功。腳本建單失敗直接 exit 1 並印回應。 已用 seed_customer_rides.sh 3 實跑驗過(ride #66-#68,全部已取消)。 2. 本機後端跑法更正為 REDIS_ADDR=127.0.0.1:6380:6379 會靜默連到 Mac 本機的 redis-server(已用 raw socket 對兩台寫 whoami 鍵驗死)。容器改發布 6380 見 dispatch PR #72。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
追加一支 commit:把這輪踩到的兩個環境坑修掉,不只是記下來
改完的閉環證據:用 6380 跑一輪建單後, |
「定位健康度」這一族的最後一個角落。TODO 原本寫「前景服務被系統收走時 App 端沒有 任何偵測」——查下去發現那句要更正:服務被收走而 App 還活著時串流會停,第二十一輪的 定期重評已經接住(第二十二輪實測 12~24 秒降級)。真正沒有網的是冷啟動: init() 會用 _restoreActiveRide() 還原進行中行程(行程卡照樣顯示導航/已上車/完成), 但 _online 一律從 false 起、定位串流也沒起來 → 整趟零位置回報。後果不在司機端: 乘客端司機 marker 定格、後端抵達圍籬不觸發、F3 里程軌跡缺一整段。而 hero 只寫 「離線/目前不會收到派單」——在載客途中,那句話講的是接不接新單。 修法兩個: 1. 冷啟動還原到進行中行程時接回定位回報。三個限制寫在碼裡:只在冷啟動做(回前景也 自動上線的話離線鈕按不掉)、只在已有權限時做(冷啟動彈權限視窗太侵入,沒權限就留 一則「需要定位權限才能把位置回報給乘客」而不是「才能上線」)、沒有行程不自動上線。 2. refreshVehicle() 不再無條件 _setError(null)——它會把排在前面設好的訊息全洗掉, 上面那句權限提示就是這樣消失的。改成只清自己造成的那則。 驗收:flutter analyze 無 issue、flutter test 383 passed(377+新 6)。 反向驗證兩半各一次,各 2 案 FAIL。模擬器實跑同一台裝置、同一張行程 #37 跑兩個版本: force-stop 後修好的版本重開 8 秒內恢復回報(hero「上線中」),修改前 40 秒零筆 (行程卡完整、hero 卻寫「離線」)。負向對照:沒有行程時冷啟動零回報。 過程中踩到一條記進 TODO:接縫的預設實作會跑進測試環境——冷啟動直接 await 平台權限 確認,讓 driver_home_widget_test 從 4.8 秒變成 7 分鐘以上(測試環境沒有 platform channel,那個 Future 永遠不會完成)。預設探針現在先看 FLUTTER_TEST 回「查不到」, 並用三態(null/denied/granted)區分「查不到」與「被拒絕」。 Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
PR #97 與 main 分岔:#94(第二十三輪)與 #95(預約司機+常用地點)先合併, docs/TODO.md 的目錄、測試數字、章節順序與 customer_controller 的 _clearSession 三處衝突。解法都是兩邊並存,不是二選一: - `_clearSession()`:分頁視窗(_historyWindow/_historyMoreError/_historyHasMore) 與常用地點/預約的清除**都要留**——兩者都是「換人登入不能留上一位的資料」。 - TODO 目錄補上第二十四輪那行(原本兩邊各刪掉對方的)。 - 「現況」的測試數字先留 main 的 414,收尾重數後再更正(寫作規則 4)。 - 第二十四輪專章接在預約司機專章之後,「下次任務」以第二十四輪那段為最新在前。 驗收:flutter analyze 無 issue、flutter test **423 passed**(main 414 + 本 PR 9)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
回頭 debug 第二十四輪自己。`_HistoryFooter` 只在 initState 觸發一次補讀,而 `loadMoreRideHistory()` 有「已經有請求在飛就 return」的重入防護:尾巴被建出來的 那一刻若剛好有下拉刷新在飛,這唯一的一次觸發就被吞掉,之後沒有任何人再試一次 ——尾巴永遠停在轉圈,舊行程的協尋與補評分入口又回到打不開的狀態。 原本 9 個案子測的是補讀本身對不對(視窗推進、錯誤分兩條、登出收回),沒有一個 案子讓兩個請求在時間上重疊,所以測不到。 修法兩個半邊,缺一不可: - 尾巴加 didUpdateWidget,每次 rebuild 都補問一次(rebuild 由 notifyListeners 帶動,刷新一結束就會走到);重入仍由 controller 擋,多問不會多打。 - 自動補讀失敗過就停手交給重試按鈕——didUpdateWidget 跟著每次 notifyListeners 觸發,少了這道 guard 會在後端還沒恢復時變成連續打點。 順手補跨年行程的年份:`_dateLabel()` 只印「1月5日 08:00」。跨年的行程是分頁上線 後才翻得到的,而這頁是事後申報遺失物、補評分的入口,找錯年份就是找錯那一趟。 驗收:flutter analyze 無 issue、flutter test 425 passed(423+新 2)。 新測試在修改前就是紅的,紅的方式本身就是證據:pumpAndSettle timed out,因為那顆 CircularProgressIndicator 永遠不會停。反向驗證兩個半邊各一次——拿掉 didUpdateWidget 新案 FAIL;拿掉「失敗就停手」guard,既有的「載入更多失敗時尾巴 給重試」那案 FAIL(27 秒逾時,正是自動重試打成迴圈的樣子)。 flutter build apk --debug --flavor customer 成功(analyze 綠不代表包得出來)。 TODO 補上第二十五輪專章,含「掃過但沒有發現問題」的七項對照表(時區、預約排序、 載入路徑、error 顯示點、.first 空集合、dispose、其他一次性觸發),免得下輪重掃。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
追加兩支 commit:解掉與 main 的衝突,並回頭 debug 這支 PR 自己(抓到 1 個永久卡死)這支開出來之後 #94(第二十三輪)與 #95(預約司機+常用地點)先合併了,本 PR 變成 一、解衝突(三處,都是兩邊並存不是二選一)
驗收: 二、🐛 回頭 debug 抓到的真 bug:分頁的尾巴會卡死在轉圈根因一句話: 症狀就是這支 PR 想修的那個病,在這條路徑上原封不動:尾巴永遠停在轉圈,第 21 筆之後的行程再也進不來,舊行程的協尋與補評分入口照樣打不開。 原本的 9 個測試為什麼抓不到:它們測的都是「補讀本身對不對」(視窗推進、錯誤分兩條、登出收回),沒有一個案子讓兩個請求在時間上重疊。這與預約那輪的教訓是同一條——沒有真的重疊的併發測試,測到的只是循序重跑。 修法兩個半邊,缺一不可:
順手補上跨年行程的年份: 三、驗收
四、這一輪掃過但沒有發現問題的(寫進 TODO,免得下一輪重掃)
五、開工前的例行實查(本輪 = 第八次)三個外部卡點依然都不在: 功能清單目前沒有「不需前置條件就能做」的項目(唯一未勾的 🤖 Generated with Claude Code |
先講開工撞到的事
TODO 寫的下一輪首選(前景服務被系統收走)已經被 #94 認領,另一支 #95 在做預約司機+常用地點。所以本輪換族,盤點「清單的資料量上限」這個從沒碰過的角。
根因
fetchRideHistory()固定要 20 筆、畫面沒有任何「載入更多」,而「我的行程」是事後聯絡司機/申報遺失物/補評分的唯一入口——第 21 趟以前的行程在乘客端永遠打不開。盤點下來這一族只有這一個真洞:對話與協尋清單都不帶 limit(後端
MaxListRows=5000),收入頁是依月聚合。後端GET /api/customer/rides的limit照單全收,所以不用動 dispatch。修法
limit、沒有 offset,所以「載入更多」是把 limit 加大重讀,不是接續抓下一段。代價是剛好整除時多要一次;好處是順帶更新已顯示那幾筆的評分/協尋狀態。historyMoreError與historyError分開——已經載進來的行程還在畫面上,錯誤只該長在清單尾巴。失敗時視窗不推進,重試要的是同一段。驗收
flutter analyze無 issue、flutter test386 passed(377 +新 9)。m6_pixel+本機 dispatch,customer flavor,以 API 造 25 筆行程 feat(app): 司機端聯絡電話填寫入口(O7 補洞)+TODO 過期勾選回填 #41–fix(driver): 沒搶到的單不再給司機一張假的行程卡 #65):LIMIT 20LIMIT 20→LIMIT 40(rows 20 → 25)pickup point 1進得來LIMIT 20pickup point 6,第 21~25 筆沒有任何入口證據取自後端 GORM 的 SQL log,不是只看畫面。dev DB 的 25 筆全部是
status=9終態。過程中踩到的兩條(已寫進 TODO)
redis-server綁127.0.0.1、docker 綁*,REDIS_ADDR=127.0.0.1:6379會連到主機那個;在容器裡redis-cli KEYS查不到鍵,會誤以為限流沒生效。line_user_id):要配速,而且每筆建完得立刻取消,否則FindActiveByCustomer擋掉下一筆。🤖 Generated with Claude Code