Blog
Catatan teknis seputar web development, DevOps, dan integrasi AI.
500 artikel
- 17.49database
Validasi Database yang Tidak Menghukum Evolusi Nilai
Tiga kolom enum-like hanya dijaga aplikasi. CHECK constraint memindahkan garansi ke database, dan evolusi nilai jadi operasi murah.
TL;DR: Dulu validasi enum cuma di aplikasi, jadi gampang jebol kalau ada insert manual iseng. Akhirnya ditambah tiga CHECK constraint di database biar nilai ngaco langsung ketolak, nggak pake ENUM native karena ribet kalau mau nambah nilai baru. Untuk tabel kecil validasi langsung full, kalau udah gede pake trik NOT VALID dulu biar nggak ngunci tabel.
#postgresql#database#testing - 17.39backend
Kontrak Endpoint Ingest yang Tahan Kegagalan Parsial
Satu angka sukses untuk seluruh batch menyembunyikan kegagalan parsial. Kontrak per-item created/updated/unchanged/rejected membuatnya terlihat.
TL;DR: Endpoint baru /v1/signals:ingest akhirnya nggak pakai satu status buat se-batch, tapi kasih status per item biar kegagalan parsial kelihatan. Tiap item bisa jadi created, updated, unchanged, atau rejected, plus ada pengaman kayak limit ukuran, jumlah item, dan rate limit. Autentikasi pakai Bearer token juga dibenerin, kalau token belum disetting server ngasih 503 bukan 401, dan semua udah dites live.
#fastapi#api#rest-api - 17.37backend
Content Hash sebagai Identitas Observasi dalam Pipeline Ingest
Observasi yang sama tercatat dua kali hanya karena nama ditulis berbeda. Content hash dari tuple kanonik menutup celah duplikasi itu.
TL;DR: Pipeline sempat ngitung dobel gara-gara nama PT ditulis beda titik sama spasi padahal perusahaannya sama. Makanya dibikin normalize_company buat beresin nama plus content_hash_for yang nge-hash tuple kanonik pakai SHA-256 biar identitasnya konsisten. Terus di database dikunci pakai UniqueConstraint dan ON CONFLICT biar duplikat nggak lolos lagi.
#postgresql#python#sqlalchemy - 16.01backend
Status Antrean Scraper yang Jujur: dari Empty sampai Recheck
Antrean scraper dengan dua status akhir menyembunyikan empat realitas. Pemisahan empty, incomplete, error, plus worklist berbasis umur data menutup celah itu.
TL;DR: Panen data macet gara-gara status cuma ada ok dan error, jadi halaman yang sukses dimuat tapi kosong nganggur di pending terus. Nambahin retry cuma buang jatah kunjungan, ternyata masalahnya bukan jaringan. Solusinya: perbanyak status jadi empty sama incomplete, tandain pas proses jalan, terus susun daftar recheck dari umur data.
#python#scraping#state-machine - 15.05backend
Rebuild Hanya untuk Pemulihan: Menjaga Ledger Tetap Sehat
Insiden rebuild yang mengubah 20 baris sehat jadi 77 UNKNOWN memaksa kontrak baru: alat pemulihan hanya mengisi kekosongan, tidak pernah menimpa baris sehat.
TL;DR: Gara-gara prinsip "raw is truth", alat rebuild malah merusak data sehat karena parser ikut baca berkas sub-tab yang bukan data detail. Kontraknya pun diubah jadi recovery-only: baris sehat dipertahankan, sub-tab diabaikan, dan ketemu UNKNOWN berarti nggak nulis apa-apa sama sekali. Karena raw-nya append-only, ledger yang sehat cukup dilengkapi, bukan ditimpa ulang.
#python#data-engineering#sqlite - 15.04backend
Melacak Jejak Panen Data dengan Log Audit SQLite
Dua penjaga lokal untuk pipeline panen data: rulebook AGENTS.md untuk agen koding dan log audit SQLite yang idempoten lewat UPSERT.
TL;DR: Pas panen data di DemandScope error terus, aku bingung commit mana yang ngasilin datanya karena Git cuma nyatet berkas berubah doang. Solusinya gampang: bikin AGENTS.md buat ngatur agen koding biar nggak sembarangan nulis data atau commit kredensial. Terus bikin log audit SQLite per target pakai UPSERT biar idempoten, jadi tiap data bisa dilacak asalnya.
#sqlite#scraping#audit-trail - 12.19backend
Saat Deep Link Berputar, Kotak Pencarian adalah Alamat
URL paginasi membawa token sesi yang terus berputar? Ambil alamat dari kotak pencarian aplikasi, lalu ratakan nilai parser sebelum dibandingkan.
TL;DR: Scraping aplikasi macam gini URL-nya sering berubah-ubah dan mati pas sesi abis, jadi jangan ribet nebak-nebak link. Mendingan ambil data lewat kotak pencarian, terus catat alurnya di log, bukan URL lengkapnya. Terakhir, samain dulu tipe datanya sebelum bandingin status, biar gak gagal gara-gara beda format.
#scraping#python#data-engineering - 11.12backend
Harvest Masuk Lewat Satu Pintu: Kontrak API yang Aman Diulang
Isolasi ruang kerja scraping dan pengiriman hasil lewat satu pintu API yang aman diulang: antrian resumable, kunci deduplikasi, ship-log.
TL;DR: Dulu scraping langsung nulis ke database aplikasi, pas sesi putus jadi bingung data mana yang udah masuk. Nah, commit ini mindahin semua alat scraping ke folder terpisah, hasil panen cuma boleh masuk lewat endpoint API ingest. Ada antrian kerja yang bisa dilanjutin plus kirim ulang yang aman berkat kunci dedup yang stabil, jadi idempoten dan bebas data dobel.
#scraping#idempotency#data-engineering - 10.28backend
Raw Dulu, Parse Belakangan: Pola Harvest yang Tahan Gagal
Pola raw dulu, parse belakangan: data mentah disimpan utuh dulu, parsing jadi proses turunan yang aman diulang saat parser berubah.
TL;DR: Scraping data dari web itu rentan mandek di tengah jalan, makanya jangan langsung parsing sambil ambil. Simpan dulu data mentahnya utuh, baru parsing terpisah lewat perintah rebuild, pakai kursor dan ledger idempoten biar bisa lanjut tanpa data dobel. Jadi kalau parser ada yang salah, tinggal perbaiki terus rebuild deh, nggak usah buka situs sumbernya lagi.
#scraping#idempotency#audit-trail