373 lines
16 KiB
PHP
373 lines
16 KiB
PHP
<?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();
|
||
?>
|