Agent 正在更新一份正式頁面。
內容已經送出。
幾秒後,連線 Timeout。
畫面只剩:
Request timeout
Agent 不知道 Server 有沒有收到。
最直覺的 Recovery 是:
Retry。
第二次 Request 送出去,這次成功。
Agent 回:
Update completed.
使用者打開頁面後,發現同一段內容出現兩次。
第一次 Request 其實早就寫進去了。
只是 Response 沒有成功回到 Client。
第二次 Retry 不是修復失敗。
而是把已經成功的 State-changing Action 又做了一次。
在 Read 操作裡,Retry 通常很直覺。
第一次查不到,就再查一次。
多數情況不會改變正式 State。
Write 不一樣。
如果 Response 不明,至少存在三種可能:
1. Request 根本沒送到
2. Request 送到,但 Write 失敗
3. Write 已成功,只是 Response 遺失
Client 看到的都可能只是:
Timeout / connection error
所以 Package 的 Action Rule 特別要求:
除非 Response 已經證明 Write 未被接受,否則不要自動 Blind Retry;先判斷 Current State,再決定下一個 Action。
如果這次 Write 是:
append comment
create object
submit approval
increment version
重送可能產生:
真正危險的是,第二次 Request 也可能完全成功。
所以從 Transport 角度看,Recovery 很漂亮。
從 Work State 看,結果反而更錯。
規則不是「永遠禁止 Retry」。
如果 Server 明確回:
Request rejected
No change applied
而且 Failure Condition 已處理,Retry 可以合理。
真正需要停下來的是:
我不知道第一次到底有沒有生效。
這時候最小下一步通常是 Readback。
例如:
Write request timed out
↓
Read current page / object / version
↓
Compare intended change
↓
Already applied? stop
Not applied? decide retry
把「不確定」先變成 Current State,再決定要不要再做一次。
很多 Tool Wrapper 都會內建 Retry。
對暫時性的 Read Error 很有用。
但如果 Agent 不知道底層 Operation 是 Read 還是 State-changing Write,就可能把同一套 Recovery 套到全部工具。
所以 Retry Policy 其實也是 Action Boundary 的一部分。
不是 Error 發生後才臨時決定。
系統在呼叫 Tool 前就應該知道:
這個 Operation 重做一次,會不會改變更多 State?
幾天後又一次 Update Timeout。
Agent 回:
Write result is uncertain.
Checking current state before retry.
它重新讀頁面。
版本已經增加。
剛才的內容也在。
所以流程停下來。
沒有第二次 Write。
使用者只看到最後一句:
更新已確認生效,未執行重送。
這次 Recovery 多了一個 Read。
卻少了一個更難清理的 Duplicate。
從那天開始,寫入結果不明時,系統不再把「再按一次」當成最安全的選項。