Kontrak webhook idempoten memastikan backend penerima bisa menangani delivery ganda tanpa mengeksekusi ulang tindakan yang sama. Untuk integrasi backend yang andal, tentukan struktur kontrak secara eksplisit: payload dengan identifier unik, header idempoten, mekanisme verifikasi, dan pengakuan penerimaan. Artikel ini langsung menjawab cara merancang kontrak tersebut beserta langkah implementasinya.
Menentukan Struktur Kontrak Webhook Idempoten
Mulai dari payload hingga header, kontrak harus memuat informasi minimal agar penerima bisa memvalidasi dan menjaga idempoten. Berikut elemen penting yang harus disepakati:
- Payload utama: sertakan
event_idataudelivery_idunik, timestamp, dan status sumber. Hindari menaruh logika di payload agar mudah divisualisasi di tracing. - Header idempoten: misal
Idempotency-Keyyang berisi UUID v4 atau kombinasi hash dari konteks event. Header ini harus diteruskan ke consumer untuk mendeteksi delivery ulang. - Signing: tandatangani payload dengan header seperti
X-SignatureatauAuthorizationyang memanfaatkan HMAC-SHA256 terhadap body danIdempotency-Key. Penerima memverifikasi signature sebelum memproses payload.
Contoh payload JSON minimal:
{
"event_id": "f3a9-12c7-4b0d",
"occurred_at": "2024-10-08T14:32:00Z",
"status": "order.paid",
"data": {
"order_id": 90210,
"amount": 142500
}
}
Header yang dikirimkan bersamaan bisa berupa:
Content-Type: application/jsonIdempotency-Key: f3a9-12c7-4b0dX-Signature: sha256=...X-Request-Timestamp: 2024-10-08T14:32:00Z(untuk mencegah replay)
Validasi Status Delivery dan Ack/Acknowledgement
Penerima harus mengirimkan respons ack untuk memberitahu pengirim bahwa payload sudah diterima dan terverifikasi. Gunakan status HTTP yang konsisten:
- 200/202: payload diterima, siap diproses. Sertakan body dengan
{"status":"accepted","idempotency_key":"..."}. - 4xx: kesalahan validasi signature atau payload. Jangan retry otomatis.
- 5xx atau timeout: indikator pengirim harus retry.
Jika ada mekanisme ack terpisah (misalnya callback queue), lampirkan identifier ack yang bisa digunakan untuk membatalkan/roll back jika diperlukan.
Mekanisme Deduplikasi dan Penyimpanan Status
Consumer harus menyimpan Idempotency-Key dan status eksekusi untuk menghindari pemrosesan ganda. Pendekatan umum:
- Simpan key + hasil (success/failure) di database transaksional atau cache dengan durasi retensi yang cukup panjang.
- Gunakan constraint unik atau upsert agar duplikasi key tidak menyebabkan lebih dari satu eksekusi.
- Setelah processing selesai, update status menjadi completed agar retry berikutnya langsung kembali 200 tanpa menjalankan logika.
Untuk rollback, pastikan perubahan database dicatat beserta key. Jika rollback terjadi sebelum ack, pengirim akan retry; jika rollback selesai tapi ack sudah dikirim, consumer perlu mencatat bahwa event sudah dianggap selesai walau kompensasi perlu dijalankan secara manual.
Strategi Retry, Backoff, dan Timeout
Pengirim harus mengimplementasikan retry dengan backoff dan timeout agar sistem tetap responsif:
- Gunakan exponential backoff dengan jitter (misal:
baseInterval * 2^attempt + random). Batasi jumlah retry untuk mencegah flood. - Timeout per request harus cukup untuk menerima ack, namun tidak terlalu besar untuk membiarkan queue menumpuk. Misalnya: timeout 5 detik untuk HTTP, lalu follow-up warm-up untuk event yang lebih berat.
- Simpan state retry di queue atau storage terpisah agar tidak kehilangan event saat restart.
Jika ada backpressure (consumer lambat), pertimbangkan circuit breaker yang menahan retry sementara dan menandai state sebagai degraded agar tim dapat intervensi.
Observabilitas: Log, Metrics, dan Tracing
Log dan metric membantu mendeteksi masalah seperti rollback atau ganda delivery:
- Log: catat
event_id,Idempotency-Key, hasil verifikasi signature, dan status ack. Jangan log payload sensitif secara utuh. - Metrics: pantau jumlah retry, error 4xx/5xx, dan latensi delivery. Gunakan label untuk membedakan event type atau consumer.
- Tracing: sertakan trace context (OpenTelemetry/W3C Trace Context) dalam header untuk menghubungkan webhook lifecycle antara pengirim dan penerima.
Jika terjadi rollback di sisi consumer, log harus menyertakan alasan dan state sebelumnya. Sementara di sisi pengirim, pantau alert ketika retry mencapai batas maksimal agar operator bisa memeriksa log atau queue backlog.
Kesimpulan
Desain kontrak webhook idempoten harus memadukan struktur payload yang jelas, header idempotensi, signing, ack yang tegas, serta deduplikasi yang terpercaya. Strategi retry/backoff dan observabilitas mengamankan alur integrasi dari delivery ganda atau gagal. Dengan kontrak yang terdokumentasi dan implementasi yang konsisten, backend dapat berkomunikasi secara andal tanpa memperkuat kompleksitas rollback.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!