Petunjuk dan konteks
Rancang penanganan konflik acara untuk produk yang serupa dengan Google Calendar. Pengguna membuat, memperbarui, dan menghapus acara dengan peserta, waktu mulai dan selesai, zona waktu, aturan pengulangan, pengingat, visibilitas, dan tautan rapat. Pembuatan atau pembaruan harus mendeteksi konflik dan mendukung kebijakan tolak (reject), peringatkan-dan-lanjutkan (warn-and-proceed), atau timpa (override). Asumsikan pembacaan ketersediaan (free/busy) jauh melebihi penulisan, pemeriksaan umum membutuhkan waktu puluhan milidetik, dan kalender pribadi hanya menampilkan status sibuk (busy).
Apa yang dievaluasi pewawancara
Jawaban yang kuat mendefinisikan semantik konflik sebelum menyebutkan nama basis data. Sinyal keberhasilannya adalah aturan interval setengah terbuka yang menghindari konflik palsu pada batas waktu; model acara kanonikal yang terpisah dari indeks tumpang tindih; batasan RRULE, pengecualian, dan materialisasi yang eksplisit; konversi dari aturan waktu lokal ke instan absolut; jalur outbox atau CDC untuk indeks turunan; serta strategi konkurensi untuk dua penulis yang memesan sumber daya yang sama. Hanya mengatakan "Kueri basis data untuk memeriksa tumpang tindih" membuat skenario kegagalan ini tidak terjawab.
Pertanyaan klarifikasi
- Apakah interval yang bersebelahan dianggap berkonflik? Jika tidak, gunakan interval setengah terbuka
[start, end). - Seberapa jauh seri berulang harus diekspansi? Seri tanpa batas memerlukan jendela bergulir (rolling window) atau ekspansi pada saat kueri dijalankan.
- Apakah setiap peserta yang sibuk memblokir acara, atau hanya peserta wajib atau penyelenggara? Hal ini menentukan fan-out kueri dan kebijakan.
- Apakah pemesanan ganda (double booking) ditolak, diberi peringatan, atau diizinkan? Ruang rapat dan kalender pribadi mungkin menggunakan kebijakan yang berbeda.
- Apakah pengguna lain boleh melihat detail lengkap, interval sibuk, atau tidak sama sekali? Hal ini menentukan ACL dan bentuk respons.
Jawaban 30 detik
"Saya memisahkan catatan kanonikal acara dan peserta dengan indeks free-busy yang dipartisi berdasarkan kalender. Konflik hanya terjadi jika existing.start < new.end dan new.start < existing.end; acara yang berstatus bebas (free) tidak menggunakan waktu ketersediaan. Saya menyimpan aturan pengulangan dalam zona waktu acara, mematerialisasikan rentang waktu terbatas, dan mencatat pengecualian. Pemeriksaan versi atau penguncian sumber daya melindungi proses penulisan, dan pola outbox memperbarui indeks turunan setelah commit. Respons hanya menampilkan informasi sibuk yang diizinkan oleh ACL, sementara pemantauan mencakup pergeseran (drift) indeks, pembangunan ulang, dan penundaan notifikasi."
Solusi langkah demi langkah
1. Tentukan waktu dan predikat konflik
Representasikan setiap kemunculan acara sebagai [start_utc, end_utc), sambil mempertahankan zona waktu asli dan aturan lokal untuk tampilan serta ekspansi. Dua kemunculan berkonflik tepat ketika a.start < b.end dan b.start < a.end. Dengan demikian, 10:00–11:00 dan 11:00–12:00 bersebelahan, bukan tumpang tindih; tolak interval dengan durasi nol atau terbalik. Konversikan acara sepanjang hari ke batas waktu dalam zona waktu kalender sebelum menerapkan predikat yang sama.
2. Pisahkan model kanonikal dari indeks ketersediaan
Lapisan kanonikal menyimpan acara, peserta, RRULE, pengecualian, ACL, dan versi untuk pengeditan dan audit. Indeks ketersediaan hanya menyimpan calendar_id, batas kemunculan, status okupansi, ID acara, dan label visibilitas, yang diurutkan berdasarkan kalender dan waktu mulai. Kueri konflik memindai jendela waktu yang diminta, bukan dokumen JSON acara yang besar. Partisi berdasarkan bulan atau tenant; kalender dengan lalu lintas tinggi mungkin memerlukan shard atau cache khusus.
3. Tangani pengulangan dan pengecualian
Simpan RRULE bergaya iCalendar dan ekspansikan kemunculan untuk rentang waktu yang diminta. Materialisasi bergulir dapat menghasilkan 90 hari ke depan dan diperpanjang saat mendekati batas; kueri yang lebih jauh diekspansikan sesuai permintaan (on-demand) dan hasilnya di-cache. this occurrence, this and future, dan pengeditan seluruh seri akan membuat catatan pengecualian atau versi seri baru daripada menulis ulang kemunculan masa lalu. Setiap kemunculan berpartisipasi secara independen dalam pemeriksaan konflik dan notifikasi.
4. Jalur penulisan dan kontrol konkurensi
Validasi waktu, ACL, dan kebijakan peserta, lalu periksa versi indeks saat ini dalam transaksi yang sama. Kalender pribadi dapat menggunakan versi optimistik dan meminta klien untuk mencoba lagi; ruangan yang benar-benar eksklusif atau slot janji temu dapat menggunakan kunci per-sumber daya atau batasan eksklusi basis data. Lakukan commit pada acara dan catatan outbox secara bersamaan; konsumen memperbarui indeks dan mengirim notifikasi. Jika indeks tertinggal, baca dari penyimpanan kanonikal atau tandai respons sebagai tidak pasti—jangan pernah mengklaim secara sepihak bahwa tidak ada konflik.
5. Privasi, kueri, dan skala
Susun respons berlapis berdasarkan ACL: pemirsa yang berwenang melihat judul dan peserta, sementara yang lain hanya melihat interval sibuk dan acara pribadi muncul sebagai blok buram. Petakan status bebas (free), tentatif, dan di luar kantor (out-of-office) ke okupansi atau peringatan sesuai kebijakan. Simpan cache jendela waktu umum untuk lalu lintas baca yang tinggi; sertakan versi kalender atau watermark pembatalan dalam kunci cache. Panggilan free/busy lintas organisasi memerlukan batas waktu (timeout) dan semantik hasil parsial agar satu kalender eksternal tidak menghambat seluruh peserta.
6. Konsistensi, perbaikan, dan penanganan kegagalan
Acara kanonikal adalah sumber kebenaran tunggal (source of truth) dan indeks dapat dibangun ulang. Pola outbox atau CDC menjamin bahwa commit yang berhasil pada akhirnya menghasilkan pembaruan indeks; konsumen memproses versi secara idempoten sehingga pesan lama tidak dapat menimpa pesan yang lebih baru. Bandingkan kemunculan kanonikal secara berkala dengan hash atau hitungan indeks, bangun ulang kalender jika terjadi pergeseran (drift), dan catat rentang yang terpengaruh. Coba lagi notifikasi yang gagal tanpa membatalkan (rollback) acara yang sudah di-commit.
Contoh jawaban berkualitas tinggi
Pertama, saya akan mendefinisikan konflik dengan [start, end): hanya perpotongan ketat yang dianggap konflik, acara yang bersebelahan tidak berkonflik, dan acara bebas tidak memakan ketersediaan waktu. Model acara kanonikal menyimpan zona waktu asli, RRULE, pengecualian, peserta, dan ACL. Indeks kemunculan terpisah yang dipartisi berdasarkan kalender hanya menyimpan batas waktu, okupansi, dan ID acara untuk pemindaian jendela waktu yang cepat. RRULE tetap berada dalam zona waktu acara; saya mematerialisasikan 90 hari ke depan, memperluas rentang yang lebih jauh sesuai permintaan, dan merepresentasikan pengeditan kemunculan tunggal, kemunculan masa depan, dan seluruh seri sebagai pengecualian atau versi eksplisit.
Jalur penulisan memvalidasi izin dan kebijakan, lalu menggunakan versi optimistik atau penguncian sumber daya untuk pengeditan bersamaan. Acara dan catatan outbox di-commit bersama-sama; konsumen yang sadar versi memperbarui indeks secara idempoten dan mengirimkan notifikasi. Indeks bersifat turunan dan dapat dibangun ulang dari data kanonikal, dan respons konflik difilter berdasarkan ACL. Saya akan memberikan peringatan daripada memblokir pemesanan ganda pada kalender pribadi, tetapi menggunakan batasan eksklusi atau penguncian untuk ruang rapat. Saya akan memantau pergeseran indeks, versi usang, latensi kueri, dan batas waktu free/busy eksternal.
Kesalahan umum
- Kesalahan: menggunakan
start <= other.enduntuk tumpang tindih → acara yang bersebelahan menjadi konflik palsu → nyatakan aturan interval setengah terbuka dan tolak acara dengan durasi nol yang tidak valid. - Kesalahan: mengekspansi seluruh seri berulang tanpa batas pada setiap permintaan → latensi dan beban kerja tidak memiliki batas atas → gunakan jendela materialisasi bergulir dan ekspansi sesuai permintaan untuk rentang di luarnya.
- Kesalahan: menggunakan seluruh JSON acara sebagai indeks konflik → operasi baca memindai data besar dan membocorkan detail pribadi → pertahankan proyeksi waktu dan okupansi saja, lalu sensor berdasarkan ACL.
- Kesalahan: membatalkan acara ketika pembaruan indeks gagal → sumber kebenaran menjadi terikat erat dengan pencarian dan notifikasi → lakukan commit ke outbox, coba lagi secara asinkron, dan sediakan mekanisme pembangunan ulang.
- Kesalahan: menggunakan kunci global untuk setiap kalender → kalender yang sibuk memperlambat seluruh layanan → kunci hanya sumber daya yang benar-benar eksklusif dan gunakan pemeriksaan versi untuk kalender biasa.
Pertanyaan lanjutan dan tanggapan
Bagaimana cara Anda menemukan waktu di mana setiap peserta berstatus bebas?
Kueri interval sibuk setiap peserta wajib untuk jendela waktu yang ditargetkan, gabungkan interval pada garis waktu yang sama, dan ambil komplemen dari gabungan (union) tersebut. Fan-out bertambah seiring bertambahnya jumlah peserta, jadi jalankan kueri secara paralel, batasi jendela waktu, dan kembalikan hasil parsial atau tidak pasti untuk kalender yang tidak memiliki izin atau mengalami timeout daripada mengekspos detail pribadi.
Rapat berulang hanya mengalami konflik pada tanggal-tanggal tertentu setelah perubahan DST (Daylight Saving Time). Bagaimana cara Anda mendebugnya?
Periksa pengidentifikasi zona waktu RRULE, waktu lokal asli, versi pustaka ekspansi, dan catatan pengecualian. Jangan mengonversi waktu lokal ke UTC lalu membuang informasi zona waktu sebelum ekspansi. Jalankan ulang kasus uji yang melintasi batas DST dan bandingkan waktu tampilan lokal setiap kemunculan, batas UTC, dan predikat tumpang tindih untuk memisahkan bug ekspansi dari bug materialisasi indeks.
Apa yang berubah jika sebuah ruangan tidak boleh dipesan ganda sama sekali?
Dua permintaan dapat melihat ruangan tersebut berstatus kosong secara bersamaan. Lindungi rentang waktu sumber daya dengan batasan eksklusi basis data, transaksi yang dapat diserialisasi (serializable transaction), atau penguncian sumber daya singkat, dan kembalikan kemunculan yang berkonflik jika gagal. Penguncian hanya mencakup jendela commit, bukan cache; buat shard untuk sumber daya yang sibuk dan batasi percobaan ulang agar antrean kunci tidak membuat kalender lain kelaparan (starvation).