feat(webstatement): optimalkan saveBatch pada ProcessStmtEntryDataJob

- **Perubahan Mekanisme Simpan Data:**
  - Mengganti pendekatan `delete` dan `insert` dengan `updateOrCreate` untuk mencegah duplicate key error.
  - Menambahkan transaksi database (`DB::beginTransaction()` dan `DB::commit()`) untuk memastikan konsistensi data.
  - Menambahkan logging pada awal dan akhir proses untuk memantau jumlah record yang berhasil diproses.

- **Penanganan Error:**
  - Menambahkan rollback transaksi (`DB::rollback()`) pada exception untuk menghindari data korup.
  - Logging eror ditingkatkan dengan menampilkan pesan dan trace exception secara rinci.

- **Optimasi Loop:**
  - Refinement looping pada `entryBatch` dengan menerapkan chunking untuk efisiensi memori.
  - Proses setiap record menggunakan `updateOrCreate` guna mengurangi overhead penghapusan data secara manual.

- **Peningkatan Logging:**
  - Menambahkan informasi log yang mencakup:
    - Proses awal dan akhir dari `saveBatch`.
    - Jumlah record yang diproses secara sukses.
    - Error yang terjadi selama proses berlangsung.

- **Dokumentasi dan Komentar:**
  - Menambahkan penjelasan detil pada method `saveBatch` untuk memperjelas logika baru.
  - Penyempurnaan komentar agar mencerminkan proses terkini dengan jelas.

Perubahan ini meningkatkan efisiensi dan keandalan proses penyimpanan data batch dengan mengurangi risiko konflik pada database serta memastikan rollback pada situasi error.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
This commit is contained in:
Daeng Deni Mardaeni
2025-06-17 09:45:41 +07:00
parent 4bfd937490
commit 2c8f49af20

View File

@@ -1,5 +1,7 @@
<?php
use Illuminate\Support\Facades\DB;
namespace Modules\Webstatement\Jobs;
use Exception;
@@ -184,33 +186,53 @@
}
/**
* Save batched records to the database
* Simpan batch data ke database menggunakan updateOrCreate
* untuk menghindari error unique constraint
*
* @return void
*/
private function saveBatch()
: void
private function saveBatch(): void
{
Log::info('Memulai proses saveBatch dengan updateOrCreate');
DB::beginTransaction();
try {
if (!empty($this->entryBatch)) {
$totalProcessed = 0;
// Process in smaller chunks for better memory management
foreach ($this->entryBatch as $entry) {
// Extract all stmt_entry_ids from the current chunk
$entryIds = array_column($entry, 'stmt_entry_id');
foreach ($this->entryBatch as $entryChunk) {
foreach ($entryChunk as $entryData) {
// Gunakan updateOrCreate untuk menghindari duplicate key error
StmtEntry::updateOrCreate(
[
'stmt_entry_id' => $entryData['stmt_entry_id']
],
$entryData
);
// Delete existing records with these IDs to avoid conflicts
StmtEntry::whereIn('stmt_entry_id', $entryIds)->delete();
// Insert all records in the chunk at once
StmtEntry::insert($entry);
$totalProcessed++;
}
}
// Reset entry batch after processing
DB::commit();
Log::info("Berhasil memproses {$totalProcessed} record dengan updateOrCreate");
// Reset entry batch after successful processing
$this->entryBatch = [];
}
} catch (Exception $e) {
DB::rollback();
Log::error("Error in saveBatch: " . $e->getMessage() . "\n" . $e->getTraceAsString());
$this->errorCount += count($this->entryBatch);
// Reset batch even if there's an error to prevent reprocessing the same failed records
$this->entryBatch = [];
throw $e;
}
}