Mempercepat Download Report Outbound dengan Multithread di Spring Boot
Proses generate report outbound di warehouse management system (WMS) bisa menjadi sangat berat—terutama ketika melibatkan ribuan hingga puluhan ribu IMEI, serial number, atau nomor HP dalam satu minggu. Jika kamu pernah mengalami proses download report yang lambat karena struktur data yang kompleks, artikel ini untukmu.
🧱 Struktur Data Outbound
Sebelum masuk ke solusi, mari pahami dulu struktur datanya:
- 1 outbound berisi banyak resi/paket
- 1 resi berisi banyak produk
- 1 produk bisa memiliki banyak IMEI / serial number / no HP
Ketika satu minggu bisa berisi ratusan paket dengan ribuan produk, total IMEI yang harus ditarik bisa mencapai puluhan ribu. Tidak heran kalau proses report terasa berat—apalagi jika semuanya dilakukan secara linier/single-thread.
🧠 Solusi: Jalankan Fetch IMEI Secara Paralel
Untuk mengatasi bottleneck ini, kita bisa menggunakan pendekatan multithread di Spring Boot, tepatnya dengan kombinasi:
CompletableFuture.supplyAsync(...)
ExecutorService
dengan thread pool tetap
Dengan cara ini, kita bisa melakukan fetch data per resi secara paralel. Hasilnya? Proses report jadi jauh lebih cepat tanpa harus mengubah struktur database.
💻 Contoh Implementasi Step by Step
1. Siapkan daftar kode resi
JAVAList<String> resiCodes = List.of("ABC", "DEF", "GHI", "JKL", "MNO");
2. Siapkan thread pool tetap
JAVAExecutorService executor = Executors.newFixedThreadPool(resiCodes.size());
Atau batasi maksimal thread-nya:
JAVAint maxThread = Math.min(5, resiCodes.size()); ExecutorService executor = Executors.newFixedThreadPool(maxThread);
3. Jalankan fetch paralel dengan CompletableFuture
JAVAList<CompletableFuture<Map.Entry<String, List<String>>>> futures = resiCodes .stream() .map(resiCode -> CompletableFuture.supplyAsync(() -> { List<String> imeis = fetchImeiByResi(resiCode); // Simulasi DB fetch return Map.entry(resiCode, imeis); }, executor)) .collect(Collectors.toList());
4. Tunggu semua task selesai
JAVACompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
5. Gabungkan semua hasilnya
JAVAMap<String, List<String>> result = new HashMap<>(); for (CompletableFuture<Map.Entry<String, List<String>>> future : futures) { Map.Entry<String, List<String>> entry = future.join(); result.put(entry.getKey(), entry.getValue()); }
6. Tutup thread pool setelah selesai
JAVAexecutor.shutdown();
✨ Hasil Akhir
Dengan pendekatan ini:
- Download report jadi lebih cepat
- Tidak perlu repot dengan konfigurasi database atau query berat
- Dapat digunakan ulang di berbagai kasus fetching paralel lainnya (produk, invoice, delivery, dll)
⚠️ Tips Implementasi
- 🔄 Kirim ID, bukan entity
Jangan lemparEntity JPA
ke thread, kirim ID/kode saja - 🧵 Jumlah thread
Gunakan thread pool maksimal 5 - 10 thread untuk kestabilan - 🐢 Hindari overload
Hindari mem-fetch semua resi sekaligus, bisa batch - 💥 Tangani error
Gunakan.exceptionally()
atau logging error disupplyAsync
- 📄 Output besar?
Pertimbangkan generate CSV/Excel file dulu baru kasih link download
📌 Contoh Method fetchImeiByResi(...)
JAVApublic List<String> fetchImeiByResi(String resiCode) { return imeiRepository.findByResiCode(resiCode) .stream() .map(Imei::getNumber) .toList(); }
🔚 Penutup
Dengan strategi multithread sederhana ini, proses generate report outbound yang awalnya berat dan lambat kini bisa diselesaikan lebih cepat dan efisien. Pendekatan ini fleksibel, scalable, dan cocok untuk sistem warehouse dengan struktur data besar dan kompleks seperti WMS.
Kalau kamu sedang mengembangkan sistem serupa, jangan ragu implementasikan pendekatan ini di service report-mu.
Happy coding 🚀