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
- Apakah POST membuat sumber daya ekspor yang persisten secara langsung? Jika ya,
201 Createddapat mendeskripsikan sumber daya tersebut; jika tidak,202dapat mengonfirmasi pekerjaan yang diterima. - Bisakah permintaan logis yang sama dicoba ulang? Jika ya, wajibkan idempotency key atau ID operasi yang disediakan oleh pemanggil.
- Apakah klien memerlukan polling, webhook, atau keduanya? Hal ini mengubah representasi status dan kontrak notifikasi.
- 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/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
202sebagai 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
202tanpa 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.