Pada aplikasi CAD berbasis browser dengan engine WASM, bug yang terlihat seperti worker hang sering kali bukan masalah komputasi geometri murni, melainkan masalah perpindahan data. Worker macet karena payload CAD WASM terlalu besar biasanya muncul saat frontend mengirim snapshot geometri, state editor, atau hasil serialisasi model dalam JSON besar ke API, lalu backend meneruskannya lagi ke queue dan worker.
Gejalanya khas: latensi request naik drastis, sebagian request berakhir dengan 413 Payload Too Large atau 502 Bad Gateway, memori worker melonjak, retry job menumpuk, dan antrean render atau simpan makin panjang. Solusinya jarang cukup dengan menaikkan limit body request. Yang dibutuhkan biasanya adalah investigasi jalur payload end-to-end, lalu redesign agar queue hanya membawa metadata kecil, sementara blob besar dipindahkan ke object storage atau alur terpisah.
Gejala yang Muncul di Produksi
Kasus ini biasanya tidak meledak sekaligus. Pada awalnya, hanya beberapa model kompleks yang gagal disimpan atau dirender. Setelah itu, efek berantai muncul di sistem lain.
Gejala dari sisi API
- Waktu respons endpoint
/saveatau/rendertiba-tiba jauh lebih lambat. - Request tertentu gagal dengan
413karena limit body di proxy atau aplikasi terlampaui. - Request yang lolos body parser tetap bisa gagal di belakang proxy sebagai
502atau timeout upstream. - CPU naik karena serialisasi, deserialisasi, dan kompresi dilakukan berulang.
Gejala dari sisi queue dan worker
- Ukuran pesan queue membesar sehingga throughput turun.
- Worker terlihat aktif, tetapi progres job tidak bergerak karena sibuk memuat payload besar ke memori.
- Proses worker OOM atau dibunuh sistem.
- Retry otomatis menambah beban karena setiap retry mengulang transfer payload besar yang sama.
Gejala dari sisi pengguna
- Tombol simpan terasa berputar lama lalu gagal tanpa pesan jelas.
- Render thumbnail atau export tidak pernah selesai.
- Model yang kecil berjalan normal, tetapi model kompleks selalu bermasalah.
Contoh log yang sering terlihat
[api] POST /v1/cad/save modelId=7f2a size_bytes=18439211 content_encoding=gzip status=502 upstream_timeout_ms=30000
[proxy] client intended to send too large body: 18439211 bytes, path=/v1/cad/render
[queue-producer] enqueue render_job modelId=7f2a payload_bytes=25100498 serialize_ms=1840
[worker] job=render_job modelId=7f2a payload_bytes=25100498 rss_mb=912 deserialization_ms=2260
[worker] job=render_job modelId=7f2a error=OOMKilled attempt=3
[scheduler] queue=render retry_backlog=148 oldest_retry_age_s=420Dari log semacam ini terlihat bahwa masalah bukan hanya di satu titik. Payload membesar sejak request masuk, lalu makin berat saat masuk queue dan diproses worker.
Akar Masalah: Mengapa Payload CAD WASM Bisa Meledak
1. Serialisasi JSON geometri terlalu besar
Banyak editor CAD browser menyimpan state dalam struktur pohon, daftar operasi parametrik, metadata seleksi, histori, dan hasil triangulasi sementara. Saat semuanya diserialisasi ke JSON, ukurannya bisa membengkak karena:
- Angka disimpan sebagai teks, bukan biner.
- Struktur yang berulang membuat overhead key JSON besar.
- Objek geometri sementara ikut tersimpan padahal tidak diperlukan untuk backend.
- State editor, histori undo/redo, dan cache viewport tercampur dengan data model inti.
Masalah bertambah parah jika frontend mengirim satu snapshot penuh untuk setiap aksi simpan, bukan delta atau referensi ke objek yang sudah ada.
2. Kompresi tidak konsisten di seluruh jalur
Payload mungkin dikompresi di browser, tetapi dibuka lagi di API lalu diserialisasi ulang sebelum masuk queue. Atau sebaliknya, API menganggap request sudah kecil karena compressed on wire, padahal setelah didekompresi ukurannya jauh lebih besar di memori.
Ini penting: ukuran di jaringan bukan satu-satunya ukuran yang relevan. Backend juga harus memperhatikan ukuran setelah parse, ukuran string di runtime, dan salinan data tambahan saat log, retry, atau enqueue.
3. Limit body request, proxy, dan queue tidak cocok untuk blob besar
Sistem backend sering dibangun dengan asumsi payload request relatif kecil. Pada alur CAD, asumsi itu gagal. Beberapa bottleneck umum:
- Limit body di reverse proxy lebih kecil dari yang dibutuhkan.
- Framework body parser membaca seluruh request ke memori.
- Sistem queue dirancang untuk pesan kecil, bukan dokumen megabyte.
- Job payload disimpan penuh di Redis, database, atau broker yang sebenarnya lebih cocok untuk metadata.
4. Retry memperparah antrian
Saat worker gagal karena OOM atau timeout, retry otomatis tampak seperti mekanisme penyelamat. Namun untuk payload besar, retry sering hanya menggandakan masalah:
- Payload besar diduplikasi ke beberapa attempt.
- Queue makin padat oleh job yang peluang suksesnya rendah.
- Worker baru memulai dari nol, mengulang deserialisasi dan download payload.
Langkah Investigasi yang Efektif
Jangan mulai dari menaikkan limit secara membabi buta. Ukur dulu ukuran payload di setiap hop. Tujuannya adalah menemukan di mana payload membesar, kapan memori melonjak, dan komponen mana yang sebenarnya tidak cocok untuk membawa blob besar.
1. Petakan jalur data end-to-end
Buat peta sederhana dari alur berikut:
- Browser menghasilkan state CAD atau hasil serialisasi WASM.
- Payload dikirim ke API.
- API mem-parse request lalu menyimpan atau meneruskan ke queue.
- Worker mengambil job dan memproses render/simpan/export.
- Hasil disimpan ke database atau object storage.
Di setiap titik, catat:
- Ukuran payload di jaringan.
- Ukuran setelah dekompresi.
- Waktu parse/serialize.
- Puncak memori proses.
- Apakah payload disalin ulang atau di-log penuh.
2. Tambahkan logging ukuran, bukan isi payload
Kesalahan umum saat debugging adalah mencatat payload penuh. Ini memperparah memori, memperbesar log, dan berisiko membocorkan data model. Yang perlu dicatat adalah metadata ukuran dan fase pemrosesan.
function summarizePayload(meta) {
return {
modelId: meta.modelId,
contentEncoding: meta.contentEncoding || 'identity',
requestBytes: meta.requestBytes,
inflatedBytes: meta.inflatedBytes,
queueBytes: meta.queueBytes,
deserializeMs: meta.deserializeMs,
serializeMs: meta.serializeMs
};
}
logger.info('cad_job_received', summarizePayload(ctx));Dengan pola ini, Anda bisa membangun histogram ukuran payload dan mencari ambang kegagalan nyata di produksi.
3. Korelasikan metrik API, queue, dan worker
Masalah payload besar hampir selalu lintas layanan. Karena itu, cari korelasi antar metrik berikut:
- API: ukuran request, durasi parse body, error 413/502, timeout upstream.
- Queue: ukuran pesan rata-rata, panjang antrean, waktu tunggu, retry rate.
- Worker: RSS memory, durasi deserialisasi, OOM kill, durasi job per ukuran payload.
Jika latensi worker naik seiring ukuran queue message, akar masalahnya kemungkinan bukan algoritme render, melainkan biaya transport dan serialisasi data.
4. Uji dengan payload sintetis
Ambil satu model kecil dan satu model besar, lalu ukur perilakunya dalam kondisi terkontrol. Variasikan:
- JSON mentah vs terkompresi.
- Payload penuh vs pointer ke object storage.
- Satu request sinkron vs upload lalu enqueue job terpisah.
Tujuannya bukan mencari benchmark absolut, tetapi membuktikan titik jenuh arsitektur yang sekarang.
Checklist Diagnosis untuk Kasus Worker Macet karena Payload CAD WASM Terlalu Besar
- Apakah frontend mengirim state editor penuh, termasuk cache atau histori yang tidak diperlukan backend?
- Apakah payload dikompresi di client tetapi dibuka lalu diserialisasi ulang di API?
- Apakah queue menyimpan blob besar, bukan hanya pointer?
- Apakah framework atau middleware membaca body penuh ke memori?
- Apakah ada batas ukuran di proxy, ingress, load balancer, atau aplikasi?
- Apakah log atau tracing secara tidak sengaja menyalin payload penuh?
- Apakah retry otomatis terjadi untuk error yang seharusnya dianggap non-retriable?
- Apakah worker memproses beberapa job besar secara paralel tanpa batas memori yang aman?
- Apakah ada format data yang lebih efisien daripada JSON untuk tahap tertentu?
- Apakah backend benar-benar membutuhkan seluruh geometri, atau cukup referensi model dan parameter render?
Perbaikan Bertahap yang Praktis
Pada sistem produksi, perbaikan terbaik biasanya dilakukan bertahap. Mulai dari mitigasi cepat untuk menghentikan kerusakan, lalu lanjut ke redesign yang lebih sehat.
Tahap 1: Pasang guardrail ukuran payload
Langkah ini tidak menyelesaikan desain, tetapi penting untuk mencegah worker rusak terus-menerus.
- Tolak request di atas ambang ukuran yang masuk akal dengan pesan error yang jelas.
- Bedakan limit untuk endpoint biasa dan endpoint upload model.
- Jangan retry job yang gagal karena payload terlalu besar atau format tidak valid.
- Tambahkan metrik distribusi ukuran payload per endpoint.
function validateCadPayload(meta) {
const MAX_REQUEST_BYTES = 8 * 1024 * 1024; // contoh ambang internal, sesuaikan sistem Anda
if (meta.requestBytes > MAX_REQUEST_BYTES) {
const err = new Error('CAD payload terlalu besar');
err.code = 'PAYLOAD_TOO_LARGE';
throw err;
}
}Walau nilainya harus disesuaikan dengan kapasitas sistem, pola validasinya penting: gagal lebih awal lebih murah daripada membiarkan payload besar masuk queue dan menghancurkan worker.
Tahap 2: Kecilkan payload yang benar-benar dikirim
Audit struktur payload dari frontend. Biasanya ada banyak bagian yang bisa dipangkas:
- Buang cache viewport, data seleksi sementara, histori undo/redo, atau hasil triangulasi yang bisa dibuat ulang.
- Kirim representasi model inti, bukan seluruh state UI editor.
- Jika memungkinkan, kirim delta perubahan, bukan snapshot penuh.
- Pilih format yang lebih ringkas untuk geometri jika memang perlu transfer data besar.
Prinsipnya: backend untuk simpan atau render tidak perlu mengetahui seluruh keadaan UI browser.
Tahap 3: Jangan masukkan blob besar ke queue
Ini perubahan arsitektur paling penting. Queue sebaiknya hanya membawa metadata kecil: ID model, lokasi blob, checksum, dan parameter kerja. Payload besar disimpan di object storage atau media penyimpanan terpisah.
Pola yang disarankan: object storage + pointer
- Frontend mengunggah payload model ke object storage atau endpoint upload khusus.
- Backend menyimpan metadata file: path, checksum, ukuran, tipe serialisasi.
- Job queue hanya berisi pointer seperti
blobKey,modelId, dan opsi render. - Worker mengunduh blob saat dibutuhkan, idealnya secara streaming atau dengan batas memori jelas.
{
"jobType": "renderModel",
"modelId": "7f2a",
"blobKey": "cad-models/7f2a/2026-08-08/state.bin",
"payloadSha256": "...",
"renderPreset": "thumbnail"
}Mengapa pendekatan ini bekerja?
- Queue tetap cepat karena pesan kecil.
- Retry tidak menggandakan blob besar di broker.
- Worker bisa mengelola unduhan dan pemrosesan secara lebih terkendali.
- Alur observabilitas lebih mudah karena ukuran blob bisa dipantau terpisah dari ukuran message queue.
Trade-off: Anda menambah satu komponen penyimpanan dan harus menangani lifecycle blob, integritas data, serta pembersihan file yatim.
Tahap 4: Terapkan kompresi dan format secara konsisten
Jika payload memang besar dan tidak bisa dihindari, buat kontrak yang jelas:
- Format apa yang dikirim: JSON, biner, atau arsip terkompresi.
- Siapa yang bertanggung jawab mengompresi dan mendekompresi.
- Apakah backend perlu menyimpan bentuk terkompresi, bentuk mentah, atau keduanya.
Masalah umum adalah data dikompresi, dibuka, dikompresi lagi, lalu dibuka lagi di worker. Ini menambah CPU dan salinan memori. Untuk blob yang hanya disimpan dan diproses di worker, sering lebih efisien menyimpan objek terkompresi apa adanya dan menghindari parse dini di API.
Tahap 5: Backpressure dan kontrol konkurensi worker
Walaupun payload sudah dipindah ke object storage, worker tetap bisa kehabisan memori jika mengambil terlalu banyak job besar sekaligus. Terapkan:
- Batas konkurensi lebih rendah untuk job render model besar.
- Klasifikasi job berdasarkan ukuran blob.
- Rate limit atau slot terpisah untuk job besar.
- Timeout yang realistis dan pembatalan job jika dependensi eksternal lambat.
queue route:
- render-small -> concurrency lebih tinggi
- render-large -> concurrency lebih rendah
- save-metadata -> queue terpisah, prioritas tinggiIni membantu mencegah satu batch model kompleks melumpuhkan seluruh sistem.
Tahap 6: Chunking bila upload tunggal tidak stabil
Untuk jaringan klien yang tidak stabil atau payload sangat besar, chunked upload bisa lebih aman daripada satu request besar. Namun chunking bukan solusi untuk queue. Chunking cocok untuk tahap upload ke storage, bukan untuk mengirim potongan model melalui antrean kerja umum.
Pilih chunking jika:
- Ukuran file model besar dan koneksi klien sering putus.
- Anda butuh resumable upload.
- Proxy atau edge memiliki limit ketat pada satu request.
Jangan pilih chunking jika masalah utamanya adalah worker memproses geometri besar di memori. Dalam kasus itu, masalah utamanya tetap arsitektur pemrosesan, bukan hanya cara upload.
Contoh Alur Redesign yang Lebih Tahan
Sebelum
- Browser serialisasi state editor penuh ke JSON.
- POST ke API
/render. - API parse seluruh body ke memori.
- API memasukkan JSON besar ke queue.
- Worker deserialisasi penuh lalu render.
Sesudah
- Browser mengekspor representasi model yang diperlukan backend saja.
- Browser upload blob ke storage melalui endpoint upload atau URL bertanda tangan.
- API menerima metadata kecil:
modelId,blobKey, checksum, ukuran, preset render. - Queue hanya memuat pointer kecil.
- Worker mengunduh blob, memvalidasi checksum, lalu memproses.
- Hasil render disimpan sebagai objek terpisah dan metadata status diperbarui.
Redesign ini memisahkan control plane dari data plane: API dan queue membawa instruksi kecil, sedangkan blob besar lewat kanal penyimpanan yang memang cocok untuk itu.
Contoh Metrik yang Sebaiknya Dipasang
cad_request_bytesper endpointcad_inflated_bytessetelah dekompresicad_queue_message_bytescad_blob_download_mscad_deserialize_mscad_worker_rss_mbcad_job_fail_total{reason="payload_too_large"}cad_job_fail_total{reason="oom"}cad_retry_backlog
Metrik ini membantu membedakan tiga kelas masalah: terlalu besar saat upload, terlalu besar saat masuk queue, atau terlalu berat saat diproses worker.
Kesalahan Umum saat Memperbaiki Masalah Ini
Hanya menaikkan limit body request
Ini sering menjadi solusi semu. Request mungkin lolos, tetapi queue dan worker tetap tidak cocok menerima blob sebesar itu.
Hanya menambah memori worker
Menambah memori bisa menunda kegagalan, tetapi tidak mengatasi biaya serialisasi, retry, dan tekanan pada broker queue.
Mengompresi tanpa kontrak yang jelas
Kompresi membantu ukuran jaringan, tetapi bisa memperburuk CPU dan salinan memori jika dilakukan berulang tanpa desain alur yang konsisten.
Mencampur state UI dan data model
Ini sumber pembengkakan payload paling sering. Backend jarang memerlukan seluruh state editor untuk operasi simpan atau render.
Pelajaran Pencegahan untuk Tim Backend
- Definisikan anggaran ukuran payload sejak awal, terutama untuk produk CAD, 3D, media, atau dokumen kompleks.
- Pisahkan jalur metadata dan blob. Queue bukan object storage.
- Tambahkan validasi ukuran dan checksum di boundary sistem.
- Desain retry dengan sadar. Error karena ukuran atau format tidak valid sebaiknya tidak di-retry otomatis.
- Ukur ukuran setelah parse, bukan hanya ukuran transfer di jaringan.
- Profilkan memori worker untuk payload besar sebelum fitur dirilis luas.
- Libatkan frontend dan backend saat mendesain format state editor agar tidak membawa data UI yang tidak dibutuhkan server.
Penutup
Dalam aplikasi programmable CAD berbasis browser dan WASM, bug backend sering terlihat seperti worker render yang macet, padahal akar masalahnya ada pada cara payload dipindahkan. Saat worker macet karena payload CAD WASM terlalu besar, perbaikannya bukan sekadar menaikkan limit request, tetapi menata ulang alur data: kurangi serialisasi yang tidak perlu, konsistenkan kompresi, hentikan blob besar masuk queue, dan terapkan backpressure.
Jika Anda sedang menghadapi kombinasi gejala seperti 413, 502, worker OOM, dan retry menumpuk, mulailah dari satu pertanyaan sederhana: apakah queue dan worker saya sedang membawa data yang seharusnya tinggal di object storage? Pada banyak kasus, jawaban itulah yang membuka jalan ke solusi yang benar.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!