$maxLimit) { Log::debug("⚠ CRITICAL: Memory limit exceeded! Stopping execution."); return false; } if ($memoryPercentage > 80) { Log::debug("⚠ WARNING: Memory usage is high (" . round($memoryPercentage, 2) . "%)"); } return true; } // Database bağlantısını yenileme fonksiyonu function refreshDatabaseConnection() { try { DB::disconnect(); DB::reconnect(); Log::debug("🔄 Database connection refreshed"); } catch (Exception $e) { Log::debug("❌ Failed to refresh database connection: " . $e->getMessage()); } } // Memory temizleme fonksiyonu function cleanupMemory() { // Tüm değişkenleri temizle unset($GLOBALS['_POST']); unset($GLOBALS['_GET']); unset($GLOBALS['_REQUEST']); // Garbage collection'ı zorla gc_collect_cycles(); // Memory kullanımını kontrol et $currentMemory = memory_get_usage(true); Log::debug("🧹 Memory cleanup completed. Current usage: " . round($currentMemory / 1024 / 1024, 2) . " MB"); } // İlk database bağlantısını kur refreshDatabaseConnection(); $documentTemplates = DB::table("document_templates")->where("y", "1")->orderByRaw('RAND()')->get(); Log::debug("Total document templates found: " . $documentTemplates->count()); // Her template için progress takibi $templateProgress = []; foreach ($documentTemplates as $documentTemplate) { $templateId = $documentTemplate->id; $cacheKey = "cron_report_builder_template_{$templateId}"; $progressCacheKey = "cron_report_builder_progress_{$templateId}"; $lastProcessedIndex = (int)setting($cacheKey, false, "0"); $progressJson = setting($progressCacheKey, false, '{"processed_count":0,"error_count":0,"success_count":0,"total_records":0}'); $progress = json_decode($progressJson, true); $templateProgress[$templateId] = [ 'cacheKey' => $cacheKey, 'progressCacheKey' => $progressCacheKey, 'lastProcessedIndex' => $lastProcessedIndex, 'progress' => $progress ]; } $maxRecordsPerRun = 1; // Her çalıştırmada her template için maksimum 1 kayıt işle (azaltıldı) $totalProcessedInThisRun = 0; $databaseRefreshCounter = 0; // Ana döngü - template'ler arasında dönüşümlü olarak ilerle while (true) { // Maksimum çalışma süresini kontrol et if ((time() - $startTime) >= $maxExecutionTime) { Log::debug("⚠ Maximum execution time ({$maxExecutionTime}s) reached. Stopping execution."); break; } // Memory kontrolü if (!checkMemoryLimit($initialMemory, $maxMemoryLimit)) { break; } $activeTemplates = 0; // Her template için bir kayıt işle foreach ($documentTemplates as $documentTemplate) { $templateId = $documentTemplate->id; // Bu template için progress bilgilerini al $progressInfo = $templateProgress[$templateId]; $cacheKey = $progressInfo['cacheKey']; $progressCacheKey = $progressInfo['progressCacheKey']; $lastProcessedIndex = $progressInfo['lastProcessedIndex']; $progress = $progressInfo['progress']; Log::debug("--- Processing Template ID: {$templateId} ---"); Log::debug("Template Name: " . ($documentTemplate->title ?? 'N/A')); $fields = json_decode($documentTemplate->fields); if(isset($fields->editorMaster)) { Log::debug("✓ Editor Master SQL found"); if(isset($fields->multipleMode)) { Log::debug("⚠ Multiple Mode detected - skipping this template"); continue; } // Master query'yi çalıştır - Database bağlantısını kontrol et try { // Log::debug("Executing Master SQL: " . $fields->editorMaster); $resultMaster = DB::select($fields->editorMaster); // Log::debug("Master query returned " . count($resultMaster) . " records"); } catch (Exception $e) { Log::debug("❌ Database error in master query: " . $e->getMessage()); refreshDatabaseConnection(); continue; } // Total records'u güncelle (ilk kez çalıştırılıyorsa) if ($progress['total_records'] == 0) { $progress['total_records'] = count($resultMaster); $templateProgress[$templateId]['progress'] = $progress; } // Bu template tamamlanmış mı kontrol et if ($lastProcessedIndex >= count($resultMaster)) { Log::debug("🎉 Template ID: {$templateId} already completed!"); unset($resultMaster); continue; } $activeTemplates++; if(isset($fields->editorDetail) && !empty($resultMaster)) { Log::debug("✓ Editor Detail SQL found and master results exist"); // Bu template için kaç kayıt işleyeceğimizi hesapla $recordsToProcess = min($maxRecordsPerRun, count($resultMaster) - $lastProcessedIndex); Log::debug("📈 Processing {$recordsToProcess} records for template {$templateId}"); $processedCount = $progress['processed_count']; $errorCount = $progress['error_count']; $successCount = $progress['success_count']; // Bu template için kayıtları işle for($i = 0; $i < $recordsToProcess; $i++) { $index = $lastProcessedIndex + $i; // Maksimum çalışma süresini kontrol et if ((time() - $startTime) >= $maxExecutionTime) { Log::debug("⚠ Maximum execution time reached. Saving progress and stopping."); // İlerlemeyi kaydet setting_put($cacheKey, $index); setting_put($progressCacheKey, json_encode([ 'processed_count' => $processedCount, 'error_count' => $errorCount, 'success_count' => $successCount, 'total_records' => $progress['total_records'] ])); break 3; // Tüm döngülerden çık } // Memory kontrolü if (!checkMemoryLimit($initialMemory, $maxMemoryLimit)) { Log::debug("⚠ Memory limit reached. Saving progress and stopping."); setting_put($cacheKey, $index); setting_put($progressCacheKey, json_encode([ 'processed_count' => $processedCount, 'error_count' => $errorCount, 'success_count' => $successCount, 'total_records' => $progress['total_records'] ])); break 3; } $rowData = $resultMaster[$index]; Log::debug("--- Processing Record " . ($index + 1) . " (Template: {$templateId}) ---"); // Convert object to array if needed $rowDataArray = is_object($rowData) ? (array)$rowData : $rowData; // Prepare POST data for the report generator $_POST = [ 'sqlCodeMaster' => $fields->editorMaster, 'sqlCodeDetail' => $fields->editorDetail ?? "", 'templateRowNo' => $fields->templateRowNo ?? 25, 'documentId' => $documentTemplate->id, 'fileNameTemplate' => $fields->fileNameTemplate ?? 'report_{line_number}', 'rowData' => $rowDataArray, 'isMultipleMode' => isset($fields->isMultipleMode) ? $fields->isMultipleMode : false, 'repeatedRows' => isset($fields->repeatedRows) ? json_encode($fields->repeatedRows) : json_encode([]), 'isSingleMode' => isset($fields->isSingleMode) ? $fields->isSingleMode : true, 'repeatRowCheckbox' => isset($fields->repeatRowCheckbox) ? $fields->repeatRowCheckbox : false, 'repeatedTableCount' => isset($fields->repeatedTableCount) ? $fields->repeatedTableCount : 1 ]; $recordStartTime = microtime(true); try { // Render the report-builder-pdf-generator view directly Log::debug("📄 Rendering report-builder-pdf-generator view..."); $response = view('admin-ajax.report-builder-pdf-generator')->render(); $recordEndTime = microtime(true); $executionTime = round(($recordEndTime - $recordStartTime) * 1000, 2); Log::debug("✅ Response generated successfully"); Log::debug("⏱️ Execution time: {$executionTime}ms"); // Increment counters after successful processing $processedCount++; $successCount++; $totalProcessedInThisRun++; } catch (Exception $e) { $recordEndTime = microtime(true); $executionTime = round(($recordEndTime - $recordStartTime) * 1000, 2); Log::debug("❌ Error processing row: " . $e->getMessage()); Log::debug("⏱️ Execution time before error: {$executionTime}ms"); $errorCount++; $totalProcessedInThisRun++; } // Progress'i güncelle $lastProcessedIndex = $index + 1; $templateProgress[$templateId]['lastProcessedIndex'] = $lastProcessedIndex; $templateProgress[$templateId]['progress']['processed_count'] = $processedCount; $templateProgress[$templateId]['progress']['error_count'] = $errorCount; $templateProgress[$templateId]['progress']['success_count'] = $successCount; // Setting'e kaydet setting_put($cacheKey, $lastProcessedIndex); setting_put($progressCacheKey, json_encode([ 'processed_count' => $processedCount, 'error_count' => $errorCount, 'success_count' => $successCount, 'total_records' => $progress['total_records'] ])); // Gelişmiş bellek temizliği unset($rowData, $rowDataArray, $response, $recordStartTime, $recordEndTime, $executionTime); cleanupMemory(); // Her 5 işlemde bir database bağlantısını yenile $databaseRefreshCounter++; if ($databaseRefreshCounter >= 5) { refreshDatabaseConnection(); $databaseRefreshCounter = 0; } // Add a small delay to prevent overwhelming the server Log::debug("⏳ Waiting 2 seconds before next record..."); sleep(2); } /* Log::debug("--- Template ID: {$templateId} Round Complete ---"); Log::debug("Current Statistics:"); Log::debug(" - Total records in master query: " . count($resultMaster)); Log::debug(" - Successfully processed: {$successCount}"); Log::debug(" - Failed to process: {$errorCount}"); Log::debug(" - Current index: {$lastProcessedIndex}"); */ } else { if(!isset($fields->editorDetail)) { Log::debug("❌ Editor Detail SQL not found"); } if(empty($resultMaster)) { Log::debug("❌ Master query returned no results"); } } } else { Log::debug("❌ Editor Master SQL not found"); } // Template işlemi sonrası memory temizliği unset($fields, $resultMaster); cleanupMemory(); } // Eğer hiç aktif template kalmadıysa döngüden çık if ($activeTemplates == 0) { Log::debug("🎉 All templates completed!"); break; } Log::debug("🔄 Completed one round for all templates. Total processed in this run: {$totalProcessedInThisRun}"); Log::debug("⏳ Waiting 5 seconds before next round..."); sleep(5); } $totalExecutionTime = time() - $startTime; $finalMemory = memory_get_usage(true); $peakMemory = memory_get_peak_usage(true); Log::debug("=== CRON REPORT BUILDER QUEUE COMPLETED ==="); Log::debug("Total execution time: {$totalExecutionTime} seconds"); Log::debug("Final memory usage: " . round($finalMemory / 1024 / 1024, 2) . " MB"); Log::debug("Peak memory usage: " . round($peakMemory / 1024 / 1024, 2) . " MB"); Log::debug("Final timestamp: " . date('Y-m-d H:i:s')); // Tüm işlemler bittikten sonra sadece başladığınız template'in progress'ini yenile if ($activeTemplates == 0) { Log::debug("🔄 All templates completed. Resetting progress for next cycle..."); // Sadece bu çalıştırmada işlem yapılan template'lerin progress'ini sıfırla foreach ($templateProgress as $templateId => $progressInfo) { $cacheKey = $progressInfo['cacheKey']; $progressCacheKey = $progressInfo['progressCacheKey']; // Eğer bu template'de işlem yapıldıysa (lastProcessedIndex > 0) progress'i sıfırla if ($progressInfo['lastProcessedIndex'] > 0) { Log::debug("🔄 Resetting progress for Template ID: {$templateId}"); setting_put($cacheKey, 0); // İndeksi sıfırla setting_put($progressCacheKey, json_encode([ 'processed_count' => 0, 'error_count' => 0, 'success_count' => 0, 'total_records' => 0 ])); } else { Log::debug("⏸️ Skipping progress reset for Template ID: {$templateId} (no processing done)"); } } Log::debug("✅ Progress reset completed for processed templates only"); } // Genel ilerleme bilgisini setting'e kaydet $overallProgress = [ 'last_run' => date('Y-m-d H:i:s'), 'execution_time' => $totalExecutionTime, 'final_memory_mb' => round($finalMemory / 1024 / 1024, 2), 'peak_memory_mb' => round($peakMemory / 1024 / 1024, 2), 'status' => ($totalExecutionTime >= $maxExecutionTime) ? 'timeout' : 'completed', 'total_processed_in_run' => $totalProcessedInThisRun ]; setting_put('cron_report_builder_overall_progress', json_encode($overallProgress)); // Final cleanup cleanupMemory(); refreshDatabaseConnection(); ?>