From 56f5a45b7d81614418ae40067b8aedca7de32492 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Mon, 4 May 2026 10:21:44 +0200 Subject: [PATCH] =?UTF-8?q?Worker=20:=20simplification=20=E2=80=94=20paged?= =?UTF-8?q?js-cli=20ne=20stream=20pas=20la=20progression=20page=20par=20pa?= =?UTF-8?q?ge=20hors=20TTY?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ora désactive le spinner par-page hors TTY et émet seulement 'Rendering: Page 1' puis directement 'Rendering N pages took…'. Sans indicateur de progression réel possible, on retire le streaming (proc_open) et on revient à exec() simple. Le worker écrit maintenant rendering/done uniquement. Co-Authored-By: Claude Sonnet 4.6 --- src/Services/PdfGenerator.php | 74 ++++------------------------------- worker.php | 32 ++------------- 2 files changed, 10 insertions(+), 96 deletions(-) diff --git a/src/Services/PdfGenerator.php b/src/Services/PdfGenerator.php index e7aed80..34b7c89 100644 --- a/src/Services/PdfGenerator.php +++ b/src/Services/PdfGenerator.php @@ -85,7 +85,7 @@ class PdfGenerator } } - public function generateFromUrlToFile(string $url, string $pdfFile, array $options = [], ?callable $onProgress = null): void + public function generateFromUrlToFile(string $url, string $pdfFile, array $options = []): void { $cmd = 'TMPDIR=' . escapeshellarg($this->config['tmp_dir']) . ' '; $cmd .= escapeshellcmd($this->config['pagedjs_bin']); @@ -98,74 +98,14 @@ class PdfGenerator $cmd .= ' --timeout ' . ($this->config['pagedjs_timeout'] * 1000); } - // proc_open pour streamer stdout/stderr ligne par ligne - $descriptors = [ - 0 => ['pipe', 'r'], - 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], - ]; - $proc = proc_open($cmd, $descriptors, $pipes); - if (!is_resource($proc)) { - throw new \Exception('Failed to spawn pagedjs-cli'); - } - fclose($pipes[0]); - - stream_set_blocking($pipes[1], false); - stream_set_blocking($pipes[2], false); - - $stderrBuffer = ''; - $partial = ['', '']; - try { - while (true) { - $status = proc_get_status($proc); - $read = [$pipes[1], $pipes[2]]; - $w = null; $e = null; - $changed = @stream_select($read, $w, $e, 1); + $output = []; + $returnCode = 0; + exec($cmd . ' 2>&1', $output, $returnCode); - if ($changed > 0) { - foreach ($read as $stream) { - $idx = ($stream === $pipes[1]) ? 0 : 1; - $chunk = fread($stream, 4096); - if ($chunk === '' || $chunk === false) continue; - if ($idx === 1) $stderrBuffer .= $chunk; - $partial[$idx] .= $chunk; - // Découpe par ligne (\n ou \r — Ora utilise \r pour les spinners) - while (preg_match('/^([^\r\n]*)[\r\n](.*)$/s', $partial[$idx], $m)) { - $line = $m[1]; - $partial[$idx] = $m[2]; - if ($line !== '' && $onProgress !== null) { - $onProgress($line); - } - } - } - } - - if (!$status['running']) { - // Vider les buffers restants - foreach ([$pipes[1], $pipes[2]] as $i => $stream) { - $idx = ($stream === $pipes[1]) ? 0 : 1; - while (($chunk = fread($stream, 4096)) !== false && $chunk !== '') { - if ($idx === 1) $stderrBuffer .= $chunk; - $partial[$idx] .= $chunk; - } - if ($partial[$idx] !== '' && $onProgress !== null) { - foreach (preg_split('/[\r\n]+/', $partial[$idx]) as $line) { - if ($line !== '') $onProgress($line); - } - } - } - break; - } - } - - fclose($pipes[1]); - fclose($pipes[2]); - $exitCode = proc_close($proc); - - if ($exitCode !== 0) { - $this->log('Paged.js CLI error (URL streaming): ' . $stderrBuffer); - throw new \Exception('PDF generation failed: ' . trim($stderrBuffer)); + if ($returnCode !== 0) { + $this->log('Paged.js CLI error (job): ' . implode("\n", $output)); + throw new \Exception('PDF generation failed: ' . implode("\n", $output)); } if (!file_exists($pdfFile)) { diff --git a/worker.php b/worker.php index d8f3a0c..aecc96f 100644 --- a/worker.php +++ b/worker.php @@ -50,42 +50,16 @@ set_time_limit(0); // Le worker tourne en arrière-plan, pas de limite $generator = new \Web2Print\Services\PdfGenerator($config); $pdfPath = $jobs->pdfPath($jobId); -$pageCount = 0; -$debugLog = $config['log_file']; -$logLine = function (string $msg) use ($debugLog, $jobId) { - @file_put_contents($debugLog, '[' . date('Y-m-d H:i:s.u') . '] [job ' . $jobId . '] ' . $msg . "\n", FILE_APPEND); -}; -$logLine('worker start, url=' . ($request['url'] ?? '?')); - -$onProgress = function (string $line) use ($jobs, $jobId, &$pageCount, $logLine) { - $logLine('stdout: ' . $line); - // pagedjs-cli utilise ora qui peut émettre via \r ; on a déjà découpé. - // Lignes typiques : "- Loading: ...", "✔ Loaded", "- Rendering: Page X" - if (preg_match('/Rendering:\s*Page\s*(\d+)/i', $line, $m)) { - $pageCount = max($pageCount, (int)$m[1]); - $jobs->writeStatus($jobId, [ - 'status' => 'rendering', - 'page' => $pageCount, - ]); - } elseif (stripos($line, 'Loaded') !== false) { - $jobs->writeStatus($jobId, ['status' => 'rendering', 'page' => 0]); - } -}; - try { - $jobs->writeStatus($jobId, ['status' => 'rendering', 'page' => 0]); + $jobs->writeStatus($jobId, ['status' => 'rendering']); $generator->generateFromUrlToFile( $request['url'], $pdfPath, - $request['options'] ?? [], - $onProgress + $request['options'] ?? [] ); - $jobs->writeStatus($jobId, [ - 'status' => 'done', - 'pages' => $pageCount, - ]); + $jobs->writeStatus($jobId, ['status' => 'done']); } catch (\Throwable $e) { $jobs->writeStatus($jobId, [ 'status' => 'error',