114 lines
2.6 KiB
JavaScript
114 lines
2.6 KiB
JavaScript
const puppeteer = require('puppeteer');
|
|
|
|
const POOL_SIZE = parseInt(process.env.BROWSER_POOL_SIZE) || 5;
|
|
const VIEWPORT_WIDTH = 1500;
|
|
const VIEWPORT_HEIGHT = 1500;
|
|
|
|
let browsers = [];
|
|
let availableBrowsers = [];
|
|
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);
|
|
availableBrowsers.push(browser);
|
|
}
|
|
|
|
console.log(`Browser pool ready with ${POOL_SIZE} browsers`);
|
|
})();
|
|
|
|
return initPromise;
|
|
}
|
|
|
|
async function acquireBrowser() {
|
|
await initPool();
|
|
|
|
// wait for available browser
|
|
while (availableBrowsers.length === 0) {
|
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
}
|
|
|
|
return availableBrowsers.pop();
|
|
}
|
|
|
|
function releaseBrowser(browser) {
|
|
availableBrowsers.push(browser);
|
|
}
|
|
|
|
// renders html and returns screenshot as buffer
|
|
async function renderHtml(html, waitTime = 1000) {
|
|
const browser = await acquireBrowser();
|
|
let page = null;
|
|
|
|
try {
|
|
page = await browser.newPage();
|
|
await page.setViewport({
|
|
width: VIEWPORT_WIDTH,
|
|
height: VIEWPORT_HEIGHT
|
|
});
|
|
|
|
await page.setContent(html, { waitUntil: ['load', 'domcontentloaded', 'networkidle0'] });
|
|
|
|
// wait for body to be ready
|
|
await page.waitForSelector('body');
|
|
|
|
// wait for any animations or laoding
|
|
await new Promise(resolve => setTimeout(resolve, waitTime));
|
|
|
|
const screenshot = await page.screenshot({
|
|
type: 'png',
|
|
fullPage: false,
|
|
encoding: 'binary'
|
|
});
|
|
|
|
return Buffer.from(screenshot);
|
|
} finally {
|
|
if (page) await page.close();
|
|
releaseBrowser(browser);
|
|
}
|
|
}
|
|
|
|
|
|
async function shutdownPool() {
|
|
console.log('Shutting down browser pool...');
|
|
|
|
for (const browser of browsers) {
|
|
await browser.close();
|
|
}
|
|
|
|
browsers = [];
|
|
availableBrowsers = [];
|
|
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
|
|
};
|