templateId = $templateId; $this->recordId = $recordId; $this->tableName = $tableName; // Create unique ID for this job instance $this->uniqueId = Str::uuid()->toString(); // Mark this as the latest job for this templateId // Cache duration should be longer than job timeout Cache::put("job_lock_render_report_{$templateId}", $this->uniqueId, $this->uniqueFor); // Low priority as requested $this->onQueue('low'); } /** * Execute the job. * * @return void */ public function handle() { // Check if this job is still the latest one for this templateId // If a newer job has been queued, cancel this one $latestJobId = Cache::get("job_lock_render_report_{$this->templateId}"); if ($latestJobId !== $this->uniqueId) { Log::info("RenderReportJob CANCELLED: Newer job detected for template_id {$this->templateId}", [ 'my_id' => $this->uniqueId, 'latest_id' => $latestJobId, 'template_id' => $this->templateId ]); return; // Silently exit } Log::debug("=== RenderReportJob STARTED ===", [ 'template_id' => $this->templateId, 'record_id' => $this->recordId, 'table_name' => $this->tableName, 'unique_id' => $this->uniqueId ]); try { $documentTemplate = DB::table("document_templates")->where("id", $this->templateId)->first(); if (!$documentTemplate) { Log::error("RenderReportJob: Template not found", ['id' => $this->templateId]); return; } $fields = json_decode($documentTemplate->fields); if (!isset($fields->editorMaster)) { Log::error("RenderReportJob: editorMaster not found in template fields"); return; } // Construct query to fetch specific record using the master query // We use the master query directly with LIMIT 1 as requested, // relying on the master query's internal ordering/randomization if present. $masterSql = trim($fields->editorMaster); // Remove trailing semicolon if present if (substr($masterSql, -1) == ';') { $masterSql = substr($masterSql, 0, -1); } // User instruction: use master query directly with limit 1 // We ignore $this->recordId here as requested $sql = $masterSql . " LIMIT 1"; try { $result = DB::select($sql); } catch (\Exception $e) { Log::error("RenderReportJob: Error executing master SQL", [ 'error' => $e->getMessage(), 'sql' => $sql ]); throw $e; } if (empty($result)) { Log::warning("RenderReportJob: No records found in master query result", [ 'template_id' => $this->templateId, 'sql' => $sql ]); return; } $rowData = $result[0]; $rowDataArray = is_object($rowData) ? (array)$rowData : $rowData; // Prepare POST data as expected by the view // Note: This modifies the global $_POST which is risky in some environments but // the view seems to rely on it. In a Job, this is isolated to this process. $_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 ]; // Check again before rendering (rendering can take a long time) if (Cache::get("job_lock_render_report_{$this->templateId}") !== $this->uniqueId) { Log::info("RenderReportJob CANCELLED (Pre-render): Newer job detected for template_id {$this->templateId}", [ 'template_id' => $this->templateId ]); return; } // Render the view Log::debug("RenderReportJob: Rendering view..."); $startTime = microtime(true); // We use view()->render() just like the cron job view('admin-ajax.report-builder-pdf-generator')->render(); $executionTime = round((microtime(true) - $startTime) * 1000, 2); Log::debug("RenderReportJob: View rendered successfully", ['time_ms' => $executionTime]); } catch (\Exception $e) { Log::error("RenderReportJob: Error processing report", [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); throw $e; } } }