Perintah dan cakupan
Pertanyaan ini menguji apakah seorang insinyur backend dapat menempatkan kontrol konkurensi pada batas HTTP. Jelaskan perbedaan antara validasi cache dan proteksi penulisan, bagaimana server membandingkan entity tag, status apa saja yang dikembalikannya, serta bagaimana penulisan basis data dan header respons tetap selaras.
Hal yang dievaluasi pewawancara
- Apakah Anda memahami perbedaan arti dari ETag, If-Match, dan If-None-Match.
- Apakah validator yang kuat (strong validator) melindungi operasi penulisan dari versi usang.
- Apakah 412, 428, dan 409 memiliki batas prakondisi dan konflik bisnis yang jelas.
- Apakah Anda memperhitungkan cache proxy, percobaan ulang, otorisasi, dan visibilitas replika.
Pertanyaan klarifikasi untuk diajukan terlebih dahulu
Pastikan apakah pembaruan menggantikan seluruh sumber daya atau hanya beberapa bidang (field), apakah klien wajib mengirimkan versi, apakah penyuntingan luring (offline) dan penggabungan (merge) didukung, apakah ETag mewakili representasi penuh atau versi bisnis, dan apakah operasi baca dan tulis melewati cache, penyeimbang beban (load balancer), atau beberapa replika basis data.
Struktur jawaban 30 detik
Kembalikan ETag pada setiap representasi sumber daya. Wajibkan If-Match pada mutasi, bandingkan dengan versi saat ini di dalam batas penulisan, dan kembalikan 412 jika tidak cocok atau 428 jika prakondisi yang diwajibkan tidak ada. Jika berhasil, naikkan (increment) versi dan kembalikan ETag baru. GET dengan If-None-Match dapat mengembalikan 304, tetapi validasi cache tidak melindungi penulisan.
Jawaban mendalam
1. Pisahkan validasi cache dari proteksi penulisan
If-None-Match berguna untuk validasi cache GET: representasi yang tidak berubah dapat menghasilkan 304. If-Match mewajibkan representasi saat ini cocok dan umum digunakan pada PUT, PATCH, atau DELETE. Cache hit tidak memberikan izin untuk menimpa sumber daya saat ini; arah perbandingan dan perilaku kegagalannya berbeda.
2. Pilih ETag yang aman untuk dibandingkan
Gunakan ETag yang kuat (strong ETag) untuk proteksi penulisan sehingga byte atau versi yang ditentukan cocok persis. ETag lemah (weak ETag) cocok untuk representasi cache yang setara secara semantik dan tidak boleh digunakan untuk mengotorisasi pembaruan yang presisi. Tag tersebut tidak boleh mengekspos urutan internal atau data sensitif; turunkan tag dari representasi kanonikal dan versi dengan salt yang tidak dapat diprediksi, setelah menerapkan pemfilteran otorisasi.
3. Jaga perbandingan dan pembaruan dalam satu batas
Baca versi saat ini, bandingkan If-Match, dan lakukan pembaruan dalam satu penulisan basis data kondisional seperti UPDATE ... WHERE id = ? AND version = ?. Nol baris yang terpengaruh berarti 412; pembaruan yang berhasil akan menaikkan versi dan menghasilkan ETag baru. Jangan melakukan kueri dalam kode aplikasi lalu mengeluarkan perintah tulis tanpa syarat (unconditional write).
4. Rancang respons kegagalan dan jalur percobaan ulang
Kembalikan 428 jika prakondisi yang diwajibkan tidak ada, 412 jika ETag tidak cocok, dan 409 untuk konflik status bisnis yang terpisah. Sertakan representasi saat ini atau petunjuk untuk mengambil ulang data, tetapi jangan menimpa secara diam-diam atas nama klien. Setelah menerima 412, klien harus melakukan GET kembali, menampilkan perbedaan (diff), atau menerapkan penggabungan bidang secara eksplisit lalu mencoba lagi dengan ETag baru; percobaan ulang otomatis memerlukan batas jumlah upaya dan idempoten yang jelas.
5. Tangani cache, replika, dan operasional
Operasi baca yang membuat ETag harus melihat hasil penulisan terbaru, atau sistem harus menetapkan batas keterlambatan baca-setelah-tulis (read-after-write delay). Proxy harus meneruskan ETag, If-Match, dan If-None-Match dengan benar, disertai kontrol cache yang sesuai untuk sumber daya sensitif. Catat ID permintaan, versi lama dan baru, hasil, serta tingkat konflik untuk menemukan klien yang menggunakan representasi usang atau replika yang tertinggal.
Contoh jawaban yang kuat
Saya akan mengembalikan strong ETag pada setiap permintaan GET, yang diturunkan dari representasi kanonikal dan versi. PUT, PATCH, dan DELETE memerlukan If-Match; basis data melakukan pembaruan kondisional berbasis versi, mengembalikan 412 jika tidak ada baris yang cocok. Prakondisi yang hilang mengikuti kebijakan antarmuka dan mengembalikan 428, sedangkan keberhasilan akan menaikkan versi dan mengembalikan ETag baru. GET dengan If-None-Match yang cocok mengembalikan 304 hanya untuk penghematan cache. Setelah 412, klien membaca ulang, menampilkan diff atau melakukan penggabungan bidang secara eksplisit, dan mencoba lagi dengan tag baru. Pembacaan di seluruh replika harus melihat versi saat ini, dan proxy harus meneruskan header kondisional. Pantau konflik, permintaan versi usang, dan kelambatan replika.
Kesalahan umum
- Hanya membandingkan timestamp klien dan mengabaikan pergeseran waktu (clock skew) atau perbedaan representasi.
- Menggunakan weak ETag untuk mengotorisasi penulisan yang presisi.
- Mengueri versi terlebih dahulu lalu menulis tanpa kondisi, sehingga memicu race condition.
- Memperlakukan 412, 409, dan 428 sebagai satu kesalahan generik yang tidak memberi langkah lanjutan bagi klien.
- Membiarkan server menimpa konflik secara diam-diam dan menghilangkan hasil edit klien.
- Menghasilkan tag hanya pada node aplikasi tanpa mempertimbangkan visibilitas cache dan replika.
Pertanyaan lanjutan
Bisakah ETag berupa versi auto-increment basis data?
Itu bisa menjadi input internal, tetapi lakukan encode pada nilainya untuk HTTP dan hindari mengekspos informasi bisnis yang sensitif. Jika representasi berubah karena pemfilteran bidang atau otorisasi, hasilkan tag pada batas representasi tersebut.
Bisakah dua bidang PATCH yang tidak tumpang tindih digabungkan secara otomatis?
Sediakan protokol penggabungan tingkat bidang secara eksplisit, tetapi tetap validasi ETag mana yang digunakan klien. Publikasikan aturan penggabungan dan non-penggabungan serta audit keputusannya; bidang yang berbeda tidak membuat setiap konflik bisnis aman untuk diabaikan.
Mengapa tidak mengembalikan 409 saja?
412 berarti prakondisi gaya If-Match gagal, 428 meminta klien untuk menyediakannya, dan 409 mendeskripsikan konflik terpisah dengan status sumber daya saat ini atau operasi bisnis. Perbedaan ini memberi tahu klien apakah harus mengambil ulang data, menambahkan header, atau mengubah tindakan.
Bagaimana cara menghindari penulisan usang melalui CDN?
Arahkan mutasi ke origin yang otoritatif dan gunakan cache untuk operasi baca. Teruskan header kondisional sesuai dengan spesifikasi, batalkan entri yang terpengaruh setelah pembaruan berhasil atau batasi tingkat keusangan data, dan pantau perbedaan antara versi origin dan tag pada edge.