Refactor image rendering to use a browser pool and update dependencies

This commit is contained in:
ImBenji
2025-12-31 18:23:15 +00:00
parent 410a78ab2b
commit f876b01529
5 changed files with 130 additions and 36 deletions

108
browserPool.js Normal file
View File

@@ -0,0 +1,108 @@
const puppeteer = require('puppeteer');
const POOL_SIZE = parseInt(process.env.BROWSER_POOL_SIZE) || 5;
const VIEWPORT_WIDTH = 3240;
const VIEWPORT_HEIGHT = 3240;
let browsers = [];
let availablePages = [];
let initPromise = null;
async function initPool() {
if (initPromise) return initPromise;
initPromise = (async () => {
console.log(`Initializing browser pool with ${POOL_SIZE} instances...`);
for (let i = 0; i < POOL_SIZE; i++) {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
browsers.push(browser);
const page = await browser.newPage();
await page.setViewport({
width: VIEWPORT_WIDTH,
height: VIEWPORT_HEIGHT
});
availablePages.push(page);
}
console.log(`Browser pool ready with ${POOL_SIZE} pages`);
})();
return initPromise;
}
async function acquirePage() {
await initPool();
// wait for available page
while (availablePages.length === 0) {
await new Promise(resolve => setTimeout(resolve, 50));
}
return availablePages.pop();
}
function releasePage(page) {
availablePages.push(page);
}
// renders html and returns screenshot as buffer
async function renderHtml(html, waitTime = 1000) {
const page = await acquirePage();
try {
await page.setContent(html, { waitUntil: 'networkidle0' });
// wait for any animations or laoding
await new Promise(resolve => setTimeout(resolve, waitTime));
const screenshot = await page.screenshot({
type: 'png',
fullPage: false
});
return screenshot;
} finally {
releasePage(page);
}
}
async function shutdownPool() {
console.log('Shutting down browser pool...');
for (const browser of browsers) {
await browser.close();
}
browsers = [];
availablePages = [];
initPromise = null;
console.log('Browser pool shut down');
}
// Graceful shutdown handlers
process.on('SIGINT', async () => {
await shutdownPool();
process.exit(0);
});
process.on('SIGTERM', async () => {
await shutdownPool();
process.exit(0);
});
module.exports = {
initPool,
renderHtml,
shutdownPool,
POOL_SIZE
};