Kontrak GraphQL menjaga agar webhook tetap idempoten dan retry-safe dengan menyamakan ekspektasi schema, metadata, dan autentikasi di antara pengirim dan penerima. Jika schema, directive, dan metadata ditetapkan secara eksplisit, penerima dapat mengenali operasi mana yang boleh dijalankan ulang tanpa efek samping.
Mengapa Kontrak GraphQL Penting untuk Webhook Idempoten
Webhooks mengandalkan HTTP POST berisi payload. Tanpa kontrak, retry otomatis atau manual dapat menyebabkan efek samping ganda karena penerima tidak tahu apakah event sudah diproses. Dengan kontrak GraphQL, pengirim menentukan jenis mutation, field metadata seperti eventId dan attempt, serta aturan idempoten melalui directive custom sehingga penerima bisa menerapkan deduplikasi, validasi, dan signing secara konsisten.
Merancang Schema GraphQL untuk Webhook Idempoten
Berikut contoh schema SDL yang menjelaskan kontrak webhook:
directive @webhookContract(idempotent: Boolean!, signed: Boolean!, metadata: [String!]!) on FIELD_DEFINITION
type WebhookPayload {
eventId: ID!
attempt: Int!
data: JSON!
signature: String
}
type Mutation {
processOrderWebhook(input: WebhookPayload!): WebhookResponse @webhookContract(idempotent: true, signed: true, metadata: ["eventId", "attempt"])
}
Directive @webhookContract memberitahu penerima bahwa mutation tersebut bersifat idempoten, harus disign, dan metadata tertentu harus divalidasi. Metadata ini juga membantu middleware membangun header dan payload yang konsisten.
Metadata untuk Idempoten
Field seperti eventId, attempt, dan timestamp membantu menentukan apakah event sudah diproses. Metadata juga digunakan untuk pencatatan audit dan deduplikasi.
Resolver Pseudocode, Signing Auth, dan Validasi Payload
Resolver harus memeriksa metadata sebelum menjalankan bisnis logic:
function processOrderWebhookResolver(input) {
if (!validateSignature(input.signature, input.data)) {
throw new AuthorizationError('Signature invalid');
}
if (isDuplicate(input.eventId, input.attempt)) {
return { status: 'duplicate' };
}
const payload = validatePayloadSchema(input.data);
startTransaction();
applyBusinessLogic(payload);
recordProcessedEvent(input.eventId, input.attempt);
commitTransaction();
return { status: 'ok' };
}
Validasi payload terdiri dari schema checking (misalnya menggunakan JSON Schema atau Zod) agar mutation GraphQL tidak menerima data yang merusak. Penandatanganan bisa menggunakan HMAC-SHA256 dengan shared secret yang ada di header X-Webhook-Signature dan payload JSON.
Strategi Signing/Token
- Gunakan
secretyang tersimpan aman dan rotasi terjadwal. - Header
X-Webhook-Timestampmembantu mencegah replay attack. - Token JWT atau HMAC cocok; periksa match antara
signaturedan payload.
Deduplikasi Event dan Retry Policy yang Terpercaya
Untuk menjamin idempoten, gunakan pola deduplikasi seperti menyimpan eventId dalam store cepat (Redis/DB) dengan TTL yang sesuai. Per-request idempotency key memegang pernyataan eksklusif bahwa event tertentu adalah satu-satunya versi yang diproses.
Retry policy penting karena event bisa dikirim ulang bila pemrosesan gagal atau tidak diakui. Kombinasikan backoff eksponensial dengan jitter untuk menghindari thundering herd:
maxRetries = 5
baseDelay = 1000 // ms
for attempt in 1..maxRetries:
delay = baseDelay * (2 ** (attempt - 1))
jitter = random(0, baseDelay)
wait(delay + jitter)
response = sendWebhook()
if response.ok:
break
Gambaran diagram teks:
send -> fail -> wait 1.2s -> retry -> fail -> wait 2.7s -> retry -> successGunakan
attempt di payload sebagai metadata agar responder tahu urutan percobaan.
Per-request Idempotency Key
- Header
X-Idempotency-Keyharus unik per event dan disimpan bersamaan status. - Jika event disetujui sebelumnya, kembalikan hasil cached tanpa menjalankan ulang.
- Key idealnya digenerate di sisi pengirim sekaligus mencakup
eventIddantimestamp.
Checklist Validasi Kontrak, Pengujian Webhook, dan Observabilitas
- Validasi Kontrak: Pastikan schema SDL, directive, dan metadata dikomunikasikan ke tim pengirim dan penerima.
- Pengujian: Gunakan stub GraphQL server dengan mutation test untuk memverifikasi idempotensi, signing, dan deduplikasi.
- Observabilitas: Catat log/trace untuk setiap event, simpan
eventId, status retry, dan waktu eksekusi. - Alert: Monitor kegagalan yang berulang, latensi retry, dan rate deduplikasi tinggi.
Checklist tambahan termasuk verifikasi TTL deduplikasi, threshold pemicu alert, dan simulasi ledakan retry bagi tim QA.
Penutup
Kontrak GraphQL untuk webhook memberikan dasar teknis bagi retry aman: schema yang jelas, directive custom, metadata idempoten, signing, deduplikasi, dan kebijakan retry eksponensial + jitter membuat integrasi lebih dapat diandalkan. Pastikan checklist validation, pengujian menyeluruh, serta observabilitas aktif guna mengawasi perilaku webhook secara nyata.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!