All checks were successful
Deploy / deploy (push) Successful in 20s
- Nouveau système de jobs : POST /jobs (async), GET /jobs/{id} (status), GET /jobs/{id}/result (PDF), DELETE /jobs/{id}
- worker.php spawné en arrière-plan via nohup, lit la sortie pagedjs-cli ligne par ligne via proc_open et écrit la progression dans tmp/job_{id}.status.json
- Migration de pagedjs-cli en install local (node_modules) pour persister le patch protocolTimeout via patch-package
- CI : déploie package.json, worker.php, patches/, et lance npm install (qui réapplique les patches via postinstall)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
89 lines
2.5 KiB
PHP
89 lines
2.5 KiB
PHP
<?php
|
|
/**
|
|
* Worker de génération PDF asynchrone.
|
|
*
|
|
* Usage : php worker.php <job_id>
|
|
* php worker.php --cleanup (nettoyage des jobs orphelins, lancé par cron)
|
|
*/
|
|
|
|
// Autoloader (mêmes règles que public/index.php)
|
|
spl_autoload_register(function ($class) {
|
|
$prefix = 'Web2Print\\';
|
|
$baseDir = __DIR__ . '/src/';
|
|
$len = strlen($prefix);
|
|
if (strncmp($prefix, $class, $len) !== 0) return;
|
|
$relativeClass = substr($class, $len);
|
|
$file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';
|
|
if (file_exists($file)) require $file;
|
|
});
|
|
|
|
$config = require __DIR__ . '/config/config.php';
|
|
|
|
$jobs = new \Web2Print\Services\JobManager($config);
|
|
|
|
// Mode cleanup orphan (cron)
|
|
if (isset($argv[1]) && $argv[1] === '--cleanup') {
|
|
$count = $jobs->cleanOrphans();
|
|
echo "Cleaned {$count} orphan jobs.\n";
|
|
exit(0);
|
|
}
|
|
|
|
if (!isset($argv[1])) {
|
|
fwrite(STDERR, "Usage: php worker.php <job_id> | --cleanup\n");
|
|
exit(1);
|
|
}
|
|
|
|
$jobId = $argv[1];
|
|
if (!preg_match('/^[a-f0-9]+$/', $jobId)) {
|
|
fwrite(STDERR, "Invalid job_id\n");
|
|
exit(1);
|
|
}
|
|
|
|
$request = $jobs->getRequest($jobId);
|
|
if ($request === null) {
|
|
fwrite(STDERR, "Request not found for job {$jobId}\n");
|
|
exit(1);
|
|
}
|
|
|
|
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;
|
|
$onProgress = function (string $line) use ($jobs, $jobId, &$pageCount) {
|
|
// 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]);
|
|
|
|
$generator->generateFromUrlToFile(
|
|
$request['url'],
|
|
$pdfPath,
|
|
$request['options'] ?? [],
|
|
$onProgress
|
|
);
|
|
|
|
$jobs->writeStatus($jobId, [
|
|
'status' => 'done',
|
|
'pages' => $pageCount,
|
|
]);
|
|
} catch (\Throwable $e) {
|
|
$jobs->writeStatus($jobId, [
|
|
'status' => 'error',
|
|
'message' => $e->getMessage(),
|
|
]);
|
|
fwrite(STDERR, "Job {$jobId} failed: " . $e->getMessage() . "\n");
|
|
exit(1);
|
|
}
|