冪等與重試¶
冪等鍵 batch_id¶
- 每個寫入請求(PUT / POST)都必須帶
batch_id(UUID v4)。 - 同一
batch_id重送時,伺服器回200 ALREADY_RECEIVED,不會重複寫入,也不會比對內容——同一batch_id以第一次收到的內容為準。
| 情況 | batch_id |
|---|---|
| 網路逾時、5xx、429 後重送 | 沿用同一個 |
| 4xx(400 / 413)修正內容後重送 | 產生新的 |
更正已送出的資料(交易 version +1、重送日結) |
產生新的 |
Warning
batch_id 產生後請先保存(例如寫入本地資料庫或檔案),重試時沿用。若程式重新啟動後產生新的 batch_id 重送同一批資料,同一筆交易會以 version 判斷,不會重複計算,但會增加不必要的處理。
重試策略¶
| 情況 | 策略 |
|---|---|
| 429 | 等待 Retry-After 秒後重試 |
| 500 / 503 / 網路逾時 | 指數退避:1、2、4、8、16…分鐘,同一 batch_id,最多持續 24 小時 |
| 401 | 不重試。檢查 API 金鑰;金鑰若已更換請聯絡總部 |
| 400 / 403 / 413 | 不重試,修正後以新 batch_id 送出 |
建議流程¶
for each batch in batches_for(store, business_date):
batch_id = uuid4() # 產生後保存,重試時沿用
loop:
resp = POST /trade-records (batch_id, batch)
if resp.status in (200, 202): break
if resp.status == 401: raise check_api_key()
if resp.status == 429: sleep(resp.Retry-After); continue
if resp.status >= 500: sleep(backoff()); continue
raise fix_required(resp.error) # 4xx:修正後用新 batch_id
POST /daily-close (new batch_id, control totals)
sleep(30 min)
GET /daily-close/{store}/{business_date} # MISMATCHED → 補送後重送 daily-close
完整可執行的程式見範例程式。