feat(v2): webhook 投递硬化——指数退避 + 最大次数死信 + 告警钩子(替裸 60s 猛敲)
This commit is contained in:
@@ -2,6 +2,7 @@ package store_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/wangjia/pay/internal/model"
|
||||
@@ -104,3 +105,35 @@ func TestEnqueueDeliveryRefundIDUnique(t *testing.T) {
|
||||
t.Fatalf("undelivered rows = %d want 3: %+v", len(rows), rows)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebhookScheduleRetryAndDead(t *testing.T) {
|
||||
ws := store.NewWebhookStore(model.OpenTestDB(t))
|
||||
now := time.Date(2026, 7, 10, 12, 0, 0, 0, time.UTC)
|
||||
_ = ws.EnqueueDelivery("PAY-1", "pangolin", "payment.succeeded", "", `{"x":1}`)
|
||||
|
||||
// 刚入队:next_attempt_at NULL → 立即可投。
|
||||
rows, _ := ws.ListDeliverable(now, 10)
|
||||
if len(rows) != 1 {
|
||||
t.Fatalf("新单应可投, got %d", len(rows))
|
||||
}
|
||||
id := rows[0].ID
|
||||
|
||||
// 排下一次重试到 now+30s:此刻不可投,过点可投。
|
||||
if err := ws.ScheduleRetry(id, "http 500", now.Add(30*time.Second)); err != nil {
|
||||
t.Fatalf("schedule: %v", err)
|
||||
}
|
||||
if r, _ := ws.ListDeliverable(now, 10); len(r) != 0 {
|
||||
t.Fatalf("退避窗内不应可投, got %d", len(r))
|
||||
}
|
||||
if r, _ := ws.ListDeliverable(now.Add(31*time.Second), 10); len(r) != 1 || r[0].Attempts != 1 {
|
||||
t.Fatalf("过退避点应可投且 attempts=1, got %+v", r)
|
||||
}
|
||||
|
||||
// 标死信:不再出现在可投集。
|
||||
if err := ws.MarkDead(id, "gave up"); err != nil {
|
||||
t.Fatalf("markdead: %v", err)
|
||||
}
|
||||
if r, _ := ws.ListDeliverable(now.Add(time.Hour), 10); len(r) != 0 {
|
||||
t.Fatalf("死信不应可投, got %d", len(r))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user