filePath = $filePath; $this->userId = $userId; $this->importId = $importId; } /** * Execute the job. * * @return void */ public function handle(): void { Log::info('ProcessSlikImport: Memulai proses import via queue', [ 'file_path' => $this->filePath, 'user_id' => $this->userId, 'import_id' => $this->importId, 'memory_limit' => ini_get('memory_limit'), 'max_execution_time' => ini_get('max_execution_time') ]); try { // Cek file size terlebih dahulu $fileSize = filesize($this->filePath); $maxFileSize = config('import.slik.max_file_size', 50) * 1024 * 1024; // Convert MB to bytes if ($fileSize > $maxFileSize) { throw new \Exception('File terlalu besar: ' . number_format($fileSize / 1024 / 1024, 2) . ' MB. Maksimum: ' . config('import.slik.max_file_size', 50) . ' MB'); } // Set optimasi memory untuk queue processing $memoryLimit = config('import.slik.memory_limit', 1024); ini_set('memory_limit', $memoryLimit . 'M'); ini_set('max_execution_time', config('import.slik.timeout', 1800)); // Set timeout untuk XML Scanner $xmlScannerTimeout = config('import.slik.xml_scanner.timeout', 1800); $xmlScannerMemory = config('import.slik.xml_scanner.memory_limit', 1024); // Enable garbage collection jika diizinkan if (config('import.slik.enable_gc', true)) { gc_enable(); } // Update progress status $this->updateProgress('processing', 0, 'Memproses file Excel...'); Log::info('SlikImport: Processing file', [ 'file' => basename($this->filePath), 'file_size' => number_format(filesize($this->filePath) / 1024 / 1024, 2) . ' MB', 'memory_limit' => $memoryLimit . 'M', 'timeout' => config('import.slik.timeout', 1800), 'enable_gc' => config('import.slik.enable_gc', true), 'xml_scanner_timeout' => config('import.slik.xml_scanner.timeout', 1800), 'chunk_size' => config('import.slik.chunk_size', 50), 'batch_size' => config('import.slik.batch_size', 50), ]); // Import file menggunakan SlikImport $import = new SlikImport(); Excel::import($import, $this->filePath); // Update progress selesai $this->updateProgress('completed', 100, 'Import berhasil diselesaikan'); Log::info('ProcessSlikImport: Import berhasil diselesaikan', [ 'import_id' => $this->importId, 'file_path' => $this->filePath, 'memory_usage' => memory_get_usage(true), 'memory_peak' => memory_get_peak_usage(true) ]); // Hapus file temporary setelah selesai if (config('import.general.cleanup_temp_files', true)) { Storage::delete($this->filePath); Log::info('ProcessSlikImport: File temporary dihapus', ['file_path' => $this->filePath]); } } catch (\Exception $e) { // Update progress error $this->updateProgress('failed', 0, 'Error: ' . $e->getMessage()); Log::error('ProcessSlikImport: Error saat proses import', [ 'import_id' => $this->importId, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'memory_usage' => memory_get_usage(true) ]); throw $e; } } /** * Update progress import * * @param string $status * @param int $percentage * @param string $message * @return void */ private function updateProgress(string $status, int $percentage, string $message): void { if (config('import.slik.progress.enabled', true)) { $cacheKey = config('import.slik.progress.cache_key', 'slik_import_progress') . '_' . $this->importId; $cacheTtl = config('import.slik.progress.cache_ttl', 3600); $progressData = [ 'status' => $status, 'percentage' => $percentage, 'message' => $message, 'timestamp' => now(), 'user_id' => $this->userId ]; cache()->put($cacheKey, $progressData, $cacheTtl); } } /** * Handle job failure * * @param \Throwable $exception * @return void */ public function failed(\Throwable $exception): void { Log::error('ProcessSlikImport: Job failed', [ 'import_id' => $this->importId, 'error' => $exception->getMessage(), 'trace' => $exception->getTraceAsString() ]); // Update progress ke failed $this->updateProgress('failed', 0, 'Import gagal: ' . $exception->getMessage()); // Cleanup file temporary if (Storage::exists($this->filePath)) { Storage::delete($this->filePath); } } }