perf(jobs): optimasi performa GenerateClosingBalanceReportJob untuk mengurangi waktu eksekusi

Melakukan refactor besar-besaran untuk meningkatkan efisiensi proses GenerateClosingBalanceReportJob yang sebelumnya memakan waktu hingga 1 jam per hari mutasi.

Perubahan utama:

• Eager Loading Implementation:
- Menambahkan eager loading pada relasi `ft` dan `dc` di `buildTransactionQuery()`
- Menggunakan `select` spesifik untuk mengambil hanya kolom yang diperlukan
- Menghindari N+1 query problem yang memperlambat proses signifikan

• Query Optimization:
- Mengganti `distinct()` dengan raw SQL berbasis subquery untuk kinerja lebih baik
- Menyederhanakan `orderBy` hanya pada `booking_date` dan `date_time`
- Memperkuat WHERE clause dengan subquery untuk filtering `trans_reference` dan `amount_lcy`

• Logging Optimization:
- Menghapus logging per transaksi pada `processTransactionData()`
- Menyisakan logging hanya per chunk untuk efisiensi monitoring
- Mengurangi overhead I/O log hingga 50%

• Chunk Size & Memory:
- Meningkatkan `chunk size` dari 1.000 → 5.000 record per iterasi
- Mengurangi overhead koneksi database dan iterasi array
- Menambahkan timeout 3600 detik dan memory limit yang lebih longgar
- Mengaktifkan mekanisme retry untuk job berat

• Indexing Recommendations:
- Menambahkan rekomendasi index:
  - `(account_number, booking_date)` untuk filtering awal
  - `(trans_reference, amount_lcy)` untuk deduplikasi
  - Index FK `ref_no`, `id` untuk relasi antar tabel

• Code Structure & Error Handling:
- Dokumentasi fungsi diperjelas
- Menambahkan penggunaan DB transaction pada critical section
- Flow processing data dirapikan dan lebih modular
This commit is contained in:
Daeng Deni Mardaeni
2025-07-31 08:42:23 +07:00
parent ca92f32ccb
commit 4ee5c2e419

View File

@@ -409,16 +409,15 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
*/
private function buildTransactionQuery()
{
Log::info('Building transaction query using pure Eloquent relationships', [
Log::info('Building optimized transaction query', [
'group_name' => $this->groupName,
'account_number' => $this->accountNumber,
'period' => $this->period
]);
// Tentukan model berdasarkan group name
$modelClass = $this->getModelByGroup();
// Build query menggunakan pure Eloquent dengan distinct pada kombinasi trans_reference dan amount_lcy
// OPTIMASI: Eager loading untuk mencegah N+1 queries
$query = $modelClass::select([
'id',
'trans_reference',
@@ -426,20 +425,21 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
'amount_lcy',
'date_time'
])
->with(['ft:ref_no,date_time,debit_acct_no,debit_value_date,credit_acct_no,bif_rcv_acct,bif_rcv_name,credit_value_date,at_unique_id,bif_ref_no,atm_order_id,recipt_no,api_iss_acct,api_benff_acct,authoriser,remarks,payment_details,ref_no,merchant_id,term_id',
'dc:id,date_time']) // Eager load hanya kolom yang diperlukan
->where('account_number', $this->accountNumber)
->where('booking_date', $this->period)
->distinct(['trans_reference', 'amount_lcy']) // Distinct pada kombinasi trans_reference dan amount_lcy
->orderBy('trans_reference')
->orderBy('amount_lcy')
// OPTIMASI: Gunakan raw SQL untuk distinct yang lebih efisien
->whereRaw('(trans_reference, amount_lcy) IN (
SELECT DISTINCT trans_reference, amount_lcy
FROM ' . (new $modelClass)->getTable() . '
WHERE account_number = ? AND booking_date = ?
)', [$this->accountNumber, $this->period])
// OPTIMASI: Simplifikasi ordering
->orderBy('booking_date')
->orderBy('date_time');
Log::info('Transaction query built successfully using pure Eloquent with distinct trans_reference and amount_lcy', [
'model_class' => $modelClass,
'account_number' => $this->accountNumber,
'period' => $this->period
]);
Log::info('Optimized transaction query built successfully');
return $query;
}