Webhook idempoten di Go Fiber memungkinkan integrasi API tetap konsisten saat client melakukan retry otomatis. Artikel ini menjelaskan langsung bagaimana merancang endpoint yang menerima retry tanpa menggandakan efek bisnis, menggunakan header khusus, penyimpanan state ringan, dan observabilitas yang diperlukan.
Memahami Idempoten dan Retry pada Webhook
Idempoten berarti menerima request berulang dengan efek yang sama seperti satu kali saja. Dalam konteks webhook, retry terjadi karena timeout, error 5xx, atau response 429 dari provider. Tanpa idempoten, request kedua bisa menyebabkan operasi bisnis berulang.
Untuk menjamin idempoten, anda perlu:
- Menerima header seperti
Idempotency-Keyyang dibangkitkan oleh pengirim. - Mencatat status dan hasil pemrosesan per key.
- Menghindari operasi non-retry-safe (misalnya increment counter) tanpa lock atau deduplikasi.
Go Fiber sangat cocok karena handler ringkas dan middleware yang mudah menyisipkan pemeriksaan state.
Membangun Skema Retry Toleran dengan Go Fiber
Menerima dan Memvalidasi Header Idempotency
Gunakan middleware untuk menolak request tanpa Idempotency-Key agar semua permintaan dapat dilacak. Header ini harus unik per operasi logis (misal: pemrosesan invoice).
Contoh middleware sederhana:
app.Use(func(c *fiber.Ctx) error {
if c.Get("Idempotency-Key") == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Idempotency-Key required"})
}
return c.Next()
})
Kunci ini digunakan untuk lookup state.
State Ringan untuk Menyimpan Status
Penyimpanan harus:
- Menampung status awal, sedang diproses, selesai.
- Menyimpan payload atau response terakhir jika perlu.
- Expire untuk mencegah pertumbuhan tak terkendali.
Simpel implementasi menggunakan in-memory map boleh untuk development, tapi produksi sebaiknya Redis atau database ringan. Contoh map sinkron:
type IdemRecord struct {
Status string
Response []byte
}
var idempotencyStore = sync.Map{}
Gunakan locking atau sync.Map agar thread-safe.
Handler Webhook dan Deduplication
Handler memeriksa store sebelum memproses:
app.Post("/webhook", func(c *fiber.Ctx) error {
key := c.Get("Idempotency-Key")
if record, exists := idempotencyStore.Load(key); exists {
return c.Status(fiber.StatusOK).Send(record.(IdemRecord).Response)
}
payload := c.Body()
// simulasikan proses bisnis
response := []byte("processed " + string(payload))
idempotencyStore.Store(key, IdemRecord{Status: "done", Response: response})
return c.Status(fiber.StatusOK).Send(response)
})
Dengan pendekatan ini, retry akan menerima response cached tanpa memanggil logika bisnis lagi.
Strategi Penanganan Timeout dan 429
Provider webhook sering melakukan retry setelah respon 429 atau waktu habis. Atasi dengan:
- Mengembalikan Gvalid 200 atau 202 begitu operation diterima, jika hasilnya belum siap. Jangan terus melempar 5xx kecuali benar-benar gagal.
- Jika sistem sedang sibuk, respon 429 dengan header
Retry-Afterlebih baik daripada memproses berlebihan. - Rekap status operasi: jika retry datang sementara proses masih berjalan, kunci status ke "processing" agar tidak memulai ganda.
Contoh update sebelum melakukan logika berat:
if _, loaded := idempotencyStore.LoadOrStore(key, IdemRecord{Status: "processing"}); loaded {
return c.Status(fiber.StatusConflict).SendString("Already processing")
}
Setelah berhasil, update ke "done".
Simulasi Retry untuk Pengujian
Pengujian penting untuk memastikan mekanisme bekerja. Gunakan unit test atau simple script yang memanggil webhook beberapa kali dengan header sama.
func testRetry() {
req := httptest.NewRequest("POST", "/webhook", strings.NewReader("invoice-123"))
req.Header.Set("Idempotency-Key", "inv-123")
resp1, _ := app.Test(req)
resp2, _ := app.Test(req)
fmt.Println(resp1.StatusCode, resp2.StatusCode)
}
Jika implementasi benar, resp2 harus segera mengembalikan hasil tanpa menjalankan logika kedua kali. Pastikan juga response body identik.
Observabilitas dan Diagnostik Duplicate
Untuk mendeteksi retry tidak sah, tambahkan metrik dan log:
- Logging setiap
Idempotency-Keybaru dan ketika membalas dengan cache. - Counter untuk request duplikat memudahkan monitoring abnormal.
- Ekspos metric ke Prometheus atau sistem observability lain.
Dengan informasi ini, Anda bisa melihat apakah provider retry terlalu agresif atau terjadi issue network.
Checklist Operasional
- Pastikan semua request masuk memiliki header
Idempotency-Keyunik. - Implementasikan penyimpanan status (in-memory, Redis, atau DB) dengan TTL.
- Tandai status "processing" untuk menghindari race condition.
- Kembalikan response cepat (200/202) untuk request yang sedang diproses.
- Log duplikat dan ekspos metrik (cache hit, duplicate count).
- Uji dengan simulasi retry dan pastikan respon identik.
- Jika respon 429 diperlukan, tambahkan
Retry-Afteragar provider tahu kapan mencoba lagi.
Kesimpulan
Skema retry dan webhook idempoten di Go Fiber dapat dicapai dengan memvalidasi header, menyimpan state ringan, serta memantau duplicate dengan observabilitas. Pendekatan ini menjaga integritas operasi bisnis walaupun client mengirim ulang request berkali-kali.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!