Files
citrus-cms/resources/views/cron-report-builder-queue.blade.php
T
2026-04-28 21:15:09 +03:00

373 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
// Memory ve execution limitleri
$maxExecutionTime = 60; // 60 saniye
$maxMemoryLimit = 256 * 1024 * 1024; // 256 MB memory limit
$startTime = time();
$initialMemory = memory_get_usage(true);
// Memory limit ayarla
ini_set('memory_limit', '256M');
ini_set('max_execution_time', $maxExecutionTime);
Log::debug("=== CRON REPORT BUILDER QUEUE STARTED ===");
Log::debug("Timestamp: " . date('Y-m-d H:i:s'));
Log::debug("Initial memory usage: " . round($initialMemory / 1024 / 1024, 2) . " MB");
Log::debug("Memory limit set to: " . round($maxMemoryLimit / 1024 / 1024, 2) . " MB");
// Memory kontrol fonksiyonu
function checkMemoryLimit($startMemory, $maxLimit) {
$currentMemory = memory_get_usage(true);
$memoryUsed = $currentMemory - $startMemory;
$memoryPercentage = ($memoryUsed / $maxLimit) * 100;
Log::debug("Memory usage: " . round($currentMemory / 1024 / 1024, 2) . " MB");
Log::debug("Memory used since start: " . round($memoryUsed / 1024 / 1024, 2) . " MB");
Log::debug("Memory usage percentage: " . round($memoryPercentage, 2) . "%");
if ($memoryUsed > $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();
?>