Topik wawancara representatif

Wawancara backend: Kapan API harus mengembalikan HTTP 202 Accepted?

BackendSedang
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Sebuah POST memulai pekerjaan yang mungkin berjalan melebihi batas waktu request timeout. Kapan API harus mengembalikan 202 Accepted, apa yang harus dimuat dalam respons, dan bagaimana Anda membuat percobaan ulang serta kegagalan dapat diobservasi?

Konteks dan skenario

Anda bertanggung jawab atas POST /exports untuk ekspor data berukuran besar. Permintaan memvalidasi input dan memulai pekerjaan, namun proses ekspor mungkin membutuhkan waktu beberapa menit. Pewawancara menanyakan apakah harus mengembalikan 200, 201, atau 202, dan bagaimana klien mengetahui hasil akhirnya.

Asumsikan server dapat menyimpan catatan ekspor secara persisten dan memasukkan pekerjaan ke dalam antrean (enqueue). Klien mungkin mengalami timeout dan mengulang permintaan. Jawabannya harus mendefinisikan kontrak, bukan sekadar menyebutkan kode status.

Hal yang diuji oleh pewawancara

  • Apakah Anda membedakan antara "sumber daya dibuat" dan "permintaan diterima untuk diproses nanti".
  • Apakah Anda memodelkan sumber daya status yang tahan lama (durable), status akhir (terminal states), dan detail kesalahan.
  • Apakah percobaan ulang dapat membuat dua ekspor atau menghilangkan respons awal.
  • Apakah pembaruan antrean dan basis data dapat diandalkan tanpa berpura-pura memiliki transaksi terdistribusi.

Pertanyaan klarifikasi sebelum menjawab

  1. Apakah POST membuat sumber daya ekspor yang persisten secara langsung? Jika ya, 201 Created dapat mendeskripsikan sumber daya tersebut; jika tidak, 202 dapat mengonfirmasi pekerjaan yang diterima.
  2. Bisakah permintaan logis yang sama dicoba ulang? Jika ya, wajibkan idempotency key atau ID operasi yang disediakan oleh pemanggil.
  3. Apakah klien memerlukan polling, webhook, atau keduanya? Hal ini mengubah representasi status dan kontrak notifikasi.
  4. Apa aturan retensi dan otorisasi untuk file yang diekspor? Pekerjaan yang telah selesai bukan berarti izin untuk mengekspos hasilnya ke setiap pemanggil.

Kerangka jawaban 30 detik

"Saya mengembalikan 202 Accepted hanya ketika pemrosesan ditunda dan hasil akhir belum siap. Saya membuat catatan pekerjaan yang persisten terlebih dahulu, lalu mengembalikan URI statusnya dan sebuah pengidentifikasi operasi. Klien melakukan polling ke URI tersebut dengan backoff atau menerima callback terotentikasi. Idempotency key memetakan percobaan ulang ke pekerjaan dan respons yang sama. Pekerjaan bergerak melalui status eksplisit seperti queued, running, succeeded, dan failed; worker dan outbox dapat dicoba ulang (retryable), dan endpoint status tetap menjadi sumber kebenaran tunggal (source of truth)."

Pembahasan mendalam langkah demi langkah

1. Memilih status dari siklus hidup sumber daya

200 OK berarti permintaan selesai dengan sebuah representasi. 201 Created berarti sebuah sumber daya telah dibuat dan harus dapat diidentifikasi. 202 Accepted berarti permintaan telah diterima, sementara pemrosesan mungkin belum dimulai atau belum selesai; ini tidak menjamin keberhasilan pada akhirnya.

Jika catatan ekspor dibuat secara sinkron dan merupakan sumber daya yang akan dikelola oleh pemanggil, saya dapat mengembalikan 201 beserta sumber daya tersebut. Jika API hanya mengonfirmasi pekerjaan dan hasilnya masih tertunda, 202 ditambah URI monitor akan lebih jelas. Pilihan ini mengikuti siklus hidup yang dapat diobservasi, bukan karena kebetulan ada antrean.

2. Buat respons dapat ditindaklanjuti

Kembalikan ID operasi, URL status, dan representasi dengan state, stempel waktu (timestamp), serta petunjuk percobaan ulang yang aman. Respons minimal dapat terlihat seperti ini:

http
HTTP/1.1 202 Accepted
Location: /exports/exp_123
Retry-After: 5
Content-Type: application/json

{"id":"exp_123","state":"queued","status_url":"/exports/exp_123"}

Sumber daya status harus menerapkan otorisasi pada setiap pembacaan. queued dan running bersifat non-terminal. succeeded menyertakan referensi unduhan berumur pendek; failed menyertakan kode kesalahan yang stabil dan petunjuk remediasi tanpa membocorkan stack trace. Klien harus dapat mentolerir sumber daya yang menghilang setelah masa retensinya berakhir.

3. Buat percobaan ulang konvergen

Wajibkan Idempotency-Key untuk operasi yang membuat pekerjaan. Simpan hash dari permintaan terkait, ID pekerjaan yang dihasilkan, dan status respons secara persisten. Kunci berulang dengan permintaan yang sama mengembalikan hasil awal; kunci yang sama dengan permintaan yang berbeda merupakan kesalahan klien. Jangan hanya menggunakan rentang waktu sebagai aturan identitas, karena percobaan ulang yang terlambat dapat tiba setelah rentang waktu tersebut.

API tetap dapat menerima dua kunci berbeda untuk dua ekspor terpisah. Idempotensi mencegah pekerjaan duplikat untuk satu operasi logis; ini tidak membuat worker beroperasi secara exactly-once.

4. Menutup celah antara basis data dan antrean

Tulis baris ekspor dan event outbox dalam satu transaksi basis data. Relay memublikasikan baris outbox yang tertunda dan menandainya telah terkirim setelah broker mengonfirmasinya. Crash dapat memublikasikan event yang sama lagi, sehingga konsumen menggunakan ID ekspor sebagai idempotency key. Ini menjaga invarian bahwa pekerjaan yang telah di-commit pada akhirnya dapat ditemukan tanpa mengklaim bahwa basis data dan broker melakukan commit secara atomik.

Worker memperbarui status dengan transisi kondisional, misalnya queued -> running -> succeeded|failed. Percobaan ulang yang basi tidak dapat mengembalikan succeeded ke running. Metrik harus mengekspos usia antrean (queue age), usia proses berjalan (running age), tingkat kegagalan terminal, dan keterlambatan outbox (outbox lag).

5. Tentukan polling, callback, dan pembatalan

Endpoint status mendukung ETag atau versi tertentu sehingga polling dapat menggunakan conditional request. Klien menerapkan exponential backoff dengan petunjuk dari server dan berhenti melakukan polling setelah mencapai status terminal. Webhook adalah optimasi, bukan satu-satunya cara untuk mengetahui hasil: pengiriman bisa gagal, sehingga klien harus melakukan rekonsiliasi dengan membaca sumber daya status.

Pembatalan adalah perintah terpisah, seperti POST /exports/exp_123/cancel. Ini hanya diterima untuk status yang dapat dibatalkan dan sifatnya sendiri idempoten. Pekerjaan yang sudah mencapai succeeded tidak dapat di-rollback oleh pembatalan yang terlambat.

Contoh jawaban berkualitas tinggi

Pertama-tama saya akan menanyakan apakah catatan ekspor adalah sumber daya yang dibuat oleh panggilan ini. Jika ya, saya dapat mengembalikan 201 dan catatan tersebut. Untuk operasi yang ditunda yang hasilnya belum siap, saya mengembalikan 202 dengan ID operasi dan URL status terotentikasi. Saya mewajibkan idempotency key, menyimpan sidik jari permintaan (request fingerprint) serta ID pekerjaan, dan mengembalikan representasi yang sama untuk percobaan ulang.

Transaksi menulis baris ekspor dan event outbox secara bersamaan. Relay dan konsumen yang idempoten menangani pengiriman setidaknya sekali (at-least-once). Mesin status (state machine) bersifat monotonik: queued, running, kemudian succeeded atau failed. Klien melakukan polling dengan conditional request dan backoff; webhook hanya berfungsi sebagai akselerator. Saya memublikasikan queue age, outbox lag, dan terminal error, serta mendefinisikan retensi, otorisasi, masa kedaluwarsa unduhan, dan pembatalan secara terpisah. 202 mengonfirmasi penerimaan permintaan, bukan keberhasilan hasil kerja.

Kesalahan umum

  • Kesalahan: Menganggap 202 sebagai bukti bahwa pekerjaan akan berhasil → Penyebab kegagalan: semantik RFC mengizinkan pemrosesan gagal atau tidak pernah dimulai → Perbaikan: ekspos kegagalan terminal dan perilaku retensi.
  • Kesalahan: Hanya mengembalikan 202 tanpa URL monitor → Penyebab kegagalan: klien tidak dapat mengetahui status tanpa menebak-nebak → Perbaikan: kembalikan sumber daya status terotentikasi dan ID operasi.
  • Kesalahan: Mengandalkan publikasi antrean setelah commit basis data → Penyebab kegagalan: crash membuat pekerjaan yang tidak dapat dilihat oleh worker mana pun → Perbaikan: gunakan transactional outbox dan relay yang dapat diputar ulang (replayable).
  • Kesalahan: Mengasumsikan antrean memberikan eksekusi exactly-once → Penyebab kegagalan: percobaan ulang dan crash dapat menduplikasi pengiriman → Perbaikan: buat konsumen menjadi idempoten dan transisi bersifat kondisional.
  • Kesalahan: Membiarkan setiap penggunaan ulang idempotency-key mengembalikan status sukses → Penyebab kegagalan: sebuah kunci dapat menyembunyikan permintaan yang telah berubah → Perbaikan: bandingkan sidik jari permintaan dan tolak jika tidak cocok.

Pertanyaan lanjutan dan tanggapan

Haruskah endpoint ini mengembalikan 201?

Kembalikan 201 ketika panggilan sinkron membuat sumber daya ekspor yang persisten dan dapat mengidentifikasinya dengan Location. Kembalikan 202 ketika hasil yang bermakna ditunda dan respons hanya mengonfirmasi penerimaan permintaan. Beberapa API dapat menggunakan 201 untuk sumber daya pekerjaan sambil tetap mengekspos status pending; dokumentasikan sumber daya mana yang dijelaskan oleh status tersebut.

Bagaimana jika klien tidak pernah melakukan polling?

Pertahankan status pekerjaan secara persisten selama periode retensi yang terdokumentasi, kirimkan webhook terotentikasi opsional, dan izinkan GET di kemudian hari berdasarkan ID operasi. Kegagalan callback tidak boleh menghapus satu-satunya jalur status. URL unduhan yang kedaluwarsa dan pemeriksaan otorisasi tetap berlaku ketika klien kembali beberapa hari kemudian.

Bisakah worker memperbarui pekerjaan dua kali?

Ya, pengiriman biasanya bersifat at-least-once. Gunakan ID ekspor yang unik, transisi status kondisional, dan penulisan output yang idempoten. Event succeeded yang duplikat seharusnya tidak berbahaya; transisi dari status terminal kembali ke running harus ditolak dan dicatat dalam log.

Sumber publik

Pertanyaan terkait