feat: media worker dispatches pdf-thumbnail and pdf-hires jobs

This commit is contained in:
Hiren Kangad
2026-03-14 11:12:41 +05:30
parent 1250ad1b72
commit 4b68e337cf
+74 -1
View File
@@ -12,9 +12,12 @@ const {
updateMediaJob, updateMediaJob,
updateImageMedia, updateImageMedia,
getImage, getImage,
updatePdfPageThumb,
updatePdfPageHires,
} = require('../db'); } = require('../db');
const { probeVideo, extractPoster } = require('../video-utils'); const { probeVideo, extractPoster } = require('../video-utils');
const { putBuffer, minioClient, MINIO_BUCKET } = require('../minio'); const { putBuffer, minioClient, MINIO_BUCKET } = require('../minio');
const { pdfRenderPage, bufferToTempFile } = require('../pdf-utils');
const POLL_INTERVAL_MS = 3000; const POLL_INTERVAL_MS = 3000;
const MAX_CONCURRENCY = 2; const MAX_CONCURRENCY = 2;
@@ -81,7 +84,16 @@ async function processJob(job) {
updateMediaJob(jobId, { status: 'processing', startedAt: new Date().toISOString() }); updateMediaJob(jobId, { status: 'processing', startedAt: new Date().toISOString() });
emitJobUpdate(boardId, jobId, imageId, 'processing'); emitJobUpdate(boardId, jobId, imageId, 'processing');
// Fetch the raw video from MinIO // PDF jobs
if (job.type === 'pdf-thumbnail' || job.type === 'pdf-hires') {
const meta = JSON.parse(job.result_json);
const dpi = job.type === 'pdf-thumbnail' ? 72 : 200;
const variant = job.type === 'pdf-thumbnail' ? 'thumb' : 'hires';
await processPdfPage(job, meta.pageNumber, dpi, variant);
return;
}
// Video poster job (original logic)
const image = getImage(imageId); const image = getImage(imageId);
if (!image) { if (!image) {
updateMediaJob(jobId, { status: 'failed', error: 'Image record not found' }); updateMediaJob(jobId, { status: 'failed', error: 'Image record not found' });
@@ -152,6 +164,67 @@ async function processJob(job) {
} }
} }
/**
* Process a single PDF page: fetch PDF from MinIO, render page, upload PNG, update DB.
*/
async function processPdfPage(job, pageNumber, dpi, variant) {
const jobId = job.id;
const imageId = job.image_id;
const boardId = job.board_id;
const image = getImage(imageId);
if (!image) {
updateMediaJob(jobId, { status: 'failed', error: 'Image record not found' });
emitJobFailed(boardId, jobId, imageId, 'Image record not found');
return;
}
const pdfBuffer = await fetchFromMinio(image.minio_path);
if (!pdfBuffer) {
updateMediaJob(jobId, { status: 'failed', error: 'Failed to fetch PDF from storage' });
emitJobFailed(boardId, jobId, imageId, 'Failed to fetch PDF from storage');
return;
}
const { tmpPath, cleanup } = bufferToTempFile(pdfBuffer, '.pdf');
try {
const pngBuffer = await pdfRenderPage(tmpPath, pageNumber, dpi);
// Asset key: strip .pdf extension and append page/variant suffix
const basePath = image.minio_path.replace(/\.pdf$/i, '');
const suffix = variant === 'thumb' ? `_p${pageNumber}_thumb.png` : `_p${pageNumber}.png`;
const assetKey = basePath + suffix;
await putBuffer(assetKey, pngBuffer, 'image/png');
// Update pdf_pages record
if (variant === 'thumb') {
updatePdfPageThumb(imageId, pageNumber, assetKey);
} else {
updatePdfPageHires(imageId, pageNumber, assetKey);
}
updateMediaJob(jobId, {
status: 'done',
finishedAt: new Date().toISOString(),
});
const eventType = variant === 'thumb' ? 'pdf-thumbnail' : 'pdf-hires';
const resultKey = variant === 'thumb' ? 'thumbAssetKey' : 'hiresAssetKey';
emitJobUpdate(boardId, jobId, imageId, 'done', {
imageId,
type: eventType,
pageNumber,
[resultKey]: assetKey,
status: 'done',
});
console.log('[media-worker] Job %s done (pdf %s, image=%s, page=%d)', jobId, variant, imageId, pageNumber);
} finally {
cleanup();
}
}
/** /**
* Fetch object from MinIO as a Buffer. * Fetch object from MinIO as a Buffer.
*/ */