Skip to content

Sync dokumen dua arah: yang layak dipercaya rajin menolak

Adityo Guni Waluyo

Pull balikin isi yang beda dari yang saya push, tanpa error. Ternyata jawabannya bukan parser yang lebih pintar, tapi peta penolakan yang presisi.

Ringkasan

Gue pull markdown terus formatnya hilang tanpa error, ternyata server Plane ngebersihin description_html pakai nh3 clean jadi rich-editor kebuang diam-diam. Akhirnya gue putar haluan, identitas dokumen dipindah ke description_stripped yang aman dan sistem milih nolak daripada maksa nebak. Makanya dibikin enam status jelas biar tau kapan harus abort daripada data ilang setengah tanpa jejak.

Saya jalankan pull, dan file Markdown di repo kembali dengan isi yang beda dari yang baru aja saya push. Nggak ada pesan error. Nggak ada konflik terdeteksi. Beberapa format teks aja yang hilang begitu aja, diganti spasi kosong.

Awalnya saya curiga ini masalah encoding biasa. Dugaan saya waktu itu: alat sinkronisasi yang baik adalah alat yang bisa menangani semua format, menerjemahkan HTML kaya kembali ke Markdown dengan mulus. Saya bahkan sempat nulis parser kustom yang agresif menebak struktur HTML yang rusak.

Ternyata dugaan saya salah besar. Setelah ngecek kode sumber Plane, saya nemu fakta bahwa server secara aktif membersihkan description_html pakai nh3.clean terhadap daftar putih tag dan atribut, sambil mencatat setiap penghapusan [4]. Struktur rich-editor yang dipaksakan masuk bakal diam-diam dibuang server. Parser menebak nggak ada gunanya lawan sanitizer yang berkata hanya pada daftar putih.

Dari situ saya putar arah: alat sinkronisasi dua arah yang bisa dipercaya bukan yang bisa menangani segalanya, melainkan yang menolak pekerjaan dengan presisi. Saya berhenti menebak dan mulai memetakan penolakan dulu, sebelum nulis logika penggabungan apa pun. Peta penolakan itu yang jadi tulang punggung plane-doc-sync.

Identitas di bidang yang nggak dimutasi

Karena description_html nggak bisa diandalkan buat perjalanan pulang-pergi yang lossless, saya alihkan strategi. Identitas dokument diamankan di description_stripped, bidang teks biasa yang dihasilkan server, satu-satunya bidang yang nggak bakal dimutasi secara diam-diam [1]. Marker-nya pun teks biasa yang kelihatan, satu baris pertama, bukan komentar HTML yang bisa lenyap kena sanitasi.

Untuk badan dokumen, isinya saya simpen sebagai literal Markdown yang di-escape di dalam elemen p dan br. Struktur rich-editor saya tolak mentah-mentah. Kalo ada format yang nggak bisa dipetakan secara aman ke Markdown, sistem menolak sinkronisasi buat entri itu. Data rusak dikit-dikit tapi jujur, lebih baik daripada lengkap tapi bohong.

Enam status, bukan cuma sukses-gagal

Saya rancang enam status hasil per entri. Bukan sekadar sukses atau gagal, karena saya perlu tahu persis kenapa sebuah sinkronisasi ditolak: sukses penuh, konflik yang butuh resolusi manual, penolakan format nggak didukung, kegagalan pengambilan pas item cermin hilang, hash drift yang nggak terjelaskan, dan pembatalan eksplisit.

Contohnya klasifikasi hash drift dengan penolakan basis mustahil. Kalo hash lokal dan server nggak cocok dan nggak ada riwayat yang jelas, sistem langsung berhenti, nggak nebak sisi mana yang benar. Terus ada ringkasan konflik meeting yang memaksa keputusan eksplisit: pull, push, atau abort. Nggak ada jalan tengah yang ambigu. Merge keputusan sendiri saya bikin union dengan dedup identitas eksak dan urutan ISO; kedengarannya kaku, tapi saya lebih percaya kegagalan yang terdokumentasi daripada koreksi otomatis yang salah.

Tabel status ini juga yang bikin gate eksternal bisa diajak kerja sama. Skill lain tinggal baca status per entri, tanpa harus paham cara merge di dalam. Enam label tadi jadi bahasa antar skill, dan bahasa itu yang mencegah satu skill nebak maksud skill lain.

Detail kecil yang bikin ketat

Kanonikalisasi normalize_body bikin perjalanan pulang-pergi tepat secara byte. Aturan yang sama disalin ke plane-init, karena skill nggak bisa saling import antar folder, jadi paritasnya dijaga lewat duplikasi yang disiplin plus regression test yang menguncinya.

Kalo item cermin hilang, sistem nyatat itu sebagai kegagalan pengambilan, bukan sinyal buat bikin ulang. Saya tahu Community Edition nggak punya arsip via API, jadi nggak ada percobaan nebak-nebak arsip yang nggak ada. Log audit isinya cuma metadata, bukan isi dokumen, dan semua penulisan file dilakukan atomik.

Kalo kamu jalanin sync kayak gini, cek dulu output-nya. Kalo kamu lihat marker teks biasa yang hilang atau dobel, itu tandanya proses parse atau render gagal di tengah jalan. Jangan dilanjut, abort aja dulu.

Membangun sinkronisasi ternyata bukan soal maksa semua data cocok. Ini soal tahu kapan harus berhenti. Saya lebih senang lihat sistem menolak pekerjaan dengan jelas daripada habisin malam nyari tahu kenapa dokumen penting kehilangan setengah paragrafnya tanpa jejak.

Sources

Artikel terkait