Day 5:我修了四個「回傳成功但沒做事」的 bug,然後自己寫了第五個——這個會花錢
一個自動重試迴圈,五分鐘燒掉月額度的 42%
我花了好幾天在修同一類 bug:功能是好的,但系統不說話。 建立內容時寫死「處理中」,可是根本沒有東西在跑 CLI 回 200 說送出成功,隔天發現線上不存在 按「重新產生逐字稿」,回傳成功,什麼也沒發生
修到第四個的時候,我自己寫了一個。而且這個會花錢。 事情經過
有一支 73 分鐘的影片,逐字稿只轉出 22 分鐘。我加了一段邏輯:發現覆蓋率不足就自動重新抓取。看起來很合理——壞掉的資料應該要能自己修好,不該要求使用者知道「按哪個強制鍵」。
部署,測試,看 log:
每輪詢一次,就開一支新的轉錄工作。 五分鐘內開了五支。
去查帳號額度:
--- --- 事發前 185 credits 事發後 1,451 credits 燒掉 1,266(月額度的 42%) 為什麼會這樣
我的程式碼是這樣寫的:
問題在於——那張表除了逐字稿,還存著「正在跑的轉錄工作編號」。
所以每一輪的實際行為是: 看到殘稿 86%,判定不足 刪掉整列,連正在跑的工作編號一起刪 往下走,發現「沒有正在跑的工作」 開一支新的 下一輪回到 1
一個看起來很單純的清理動作,順手把別的狀態也清掉了。 真正該學的不是「小心 delete」
如果結論停在「刪除前要看清楚刪到什麼」,那太便宜了。這件事有三層更值得記的東西。 一、「回傳成功」不等於「有進展」
每一輪都回傳:
完全正確。伺服器確實成功受理了、確實有一支工作正在跑。從回傳值看,這系統健康得很。
但它一直在原地。狀態的證據不是進度的證據——一個永遠回「處理中」的系統,跟一個正常運作的系統,回傳值長得一模一樣。
如果那個回傳裡帶著「這是第幾次嘗試」或「工作編號」,我第一輪就會發現編號一直在變。可觀測性不是多印 log,是讓「沒有進展」這件事本身變成看得見的資料。 二、會花錢的重試,一定要有次數上限
我的重抓邏輯沒有任何上限。
而它的單價不低——一支 57 分鐘的影片重抓一次約 116 credits,是月額度的 4%。使用者只要反覆進那個頁面,就會反覆付費。
更關鍵的是:重抓不保證更好。同一支影片我實測先後拿到三種結果——22 分鐘、67 分鐘、幾乎空白。既然結果不穩定,「再試一次」就不是免費的樂觀,而是用錢買一張彩券。
最後的修法是:試過一次仍不足,就把「已經試過」記下來,之後直接告訴使用者「這份只到第 49 分鐘」,不再重試。
能自動修復的前提,是修復本身要便宜且單調遞增。 只要有一項不成立,就該停下來問人,而不是默默重試。 三、監控門檻要分「慢慢用完」和「失速」
帳號本來就有額度監控,每天檢查、超過 80% 發通知。
這次從 6% 衝到 48%——全程沒有任何告警。
80% 這個門檻的預設情境是「正常使用逐漸逼近上限」。它對「幾分鐘內失控」完全無效,因為等到 80% 的時候,錢已經花掉了。
兩種故障模式需要兩種偵測:
模式 該看什麼 --- --- 慢慢用完 絕對水位(80%) 失速 變化率(單位時間內的增量)
我先把門檻降到 50% 止血,但那只是讓同樣的錯誤早一點被抓到。真正對的做法是監控「增速」——一小時內用掉 5% 就該叫,不管總量在哪裡。 最後一件事
最諷刺的地方是:我當時正在修的,就是「回傳成功但實際沒做事」這一類的 bug。改到第四個,自己寫出第五個。
這不是巧合。當你在處理某一類問題時,你的注意力都在「找出它」,而不在「別製造它」。 而且新寫的程式碼沒有經歷過那些讓舊程式碼變可疑的失敗,看起來總是比較無辜。
真正把它抓出來的不是我的判斷,是去看 log。回傳值說一切正常,log 說每分鐘開一支新工作。 當你要確認一件事有沒有成功,不要問「它回傳什麼」,要問「它留下了什麼痕跡」。