115 lines
4.9 KiB
JavaScript
115 lines
4.9 KiB
JavaScript
import { chromium, firefox, webkit } from 'playwright';
|
|
export class BrowserPool {
|
|
browsers = new Map();
|
|
maxBrowsers;
|
|
browserTypes;
|
|
currentBrowserIndex = 0;
|
|
headless;
|
|
lastUsedBrowserType = '';
|
|
constructor() {
|
|
// Read configuration from environment variables
|
|
this.maxBrowsers = parseInt(process.env.MAX_BROWSERS || '3', 10);
|
|
this.headless = process.env.BROWSER_HEADLESS !== 'false'; // Default to true
|
|
// Configure browser types based on environment
|
|
const browserTypesEnv = process.env.BROWSER_TYPES || 'chromium,firefox';
|
|
this.browserTypes = browserTypesEnv.split(',').map(type => type.trim());
|
|
console.log(`[BrowserPool] Configuration: maxBrowsers=${this.maxBrowsers}, headless=${this.headless}, types=${this.browserTypes.join(',')}`);
|
|
}
|
|
async getBrowser() {
|
|
// Rotate between browser types for variety
|
|
const browserType = this.browserTypes[this.currentBrowserIndex % this.browserTypes.length];
|
|
this.currentBrowserIndex++;
|
|
this.lastUsedBrowserType = browserType;
|
|
if (this.browsers.has(browserType)) {
|
|
const browser = this.browsers.get(browserType);
|
|
// Check if browser is still connected and healthy
|
|
try {
|
|
if (browser.isConnected()) {
|
|
// Quick health check by trying to create and close a context
|
|
// Use minimal options to avoid Firefox isMobile issues
|
|
const testContext = await browser.newContext({
|
|
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
|
|
});
|
|
await testContext.close();
|
|
return browser;
|
|
}
|
|
}
|
|
catch (error) {
|
|
console.log(`[BrowserPool] Browser ${browserType} health check failed:`, error);
|
|
// Browser is unhealthy, remove it and close if possible
|
|
this.browsers.delete(browserType);
|
|
try {
|
|
await browser.close();
|
|
}
|
|
catch (closeError) {
|
|
console.log(`[BrowserPool] Error closing unhealthy browser:`, closeError);
|
|
}
|
|
}
|
|
}
|
|
// Launch new browser
|
|
console.log(`[BrowserPool] Launching new ${browserType} browser`);
|
|
const launchOptions = {
|
|
headless: this.headless,
|
|
args: [
|
|
'--no-sandbox',
|
|
'--disable-blink-features=AutomationControlled',
|
|
'--disable-dev-shm-usage',
|
|
'--disable-gpu',
|
|
'--no-first-run',
|
|
'--no-default-browser-check',
|
|
'--disable-default-apps',
|
|
'--disable-extensions',
|
|
'--disable-background-timer-throttling',
|
|
'--disable-backgrounding-occluded-windows',
|
|
'--disable-renderer-backgrounding',
|
|
'--disable-features=TranslateUI',
|
|
'--disable-ipc-flooding-protection',
|
|
],
|
|
};
|
|
let browser;
|
|
try {
|
|
switch (browserType) {
|
|
case 'chromium':
|
|
browser = await chromium.launch(launchOptions);
|
|
break;
|
|
case 'firefox':
|
|
browser = await firefox.launch(launchOptions);
|
|
break;
|
|
case 'webkit':
|
|
browser = await webkit.launch(launchOptions);
|
|
break;
|
|
default:
|
|
browser = await chromium.launch(launchOptions);
|
|
}
|
|
this.browsers.set(browserType, browser);
|
|
// Clean up old browsers if we have too many
|
|
if (this.browsers.size > this.maxBrowsers) {
|
|
const oldestBrowser = this.browsers.entries().next().value;
|
|
if (oldestBrowser) {
|
|
try {
|
|
await oldestBrowser[1].close();
|
|
}
|
|
catch (error) {
|
|
console.error(`[BrowserPool] Error closing old browser:`, error);
|
|
}
|
|
this.browsers.delete(oldestBrowser[0]);
|
|
}
|
|
}
|
|
return browser;
|
|
}
|
|
catch (error) {
|
|
console.error(`[BrowserPool] Failed to launch ${browserType} browser:`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
async closeAll() {
|
|
console.log(`[BrowserPool] Closing ${this.browsers.size} browsers`);
|
|
const closePromises = Array.from(this.browsers.values()).map(browser => browser.close().catch(error => console.error('Error closing browser:', error)));
|
|
await Promise.all(closePromises);
|
|
this.browsers.clear();
|
|
}
|
|
getLastUsedBrowserType() {
|
|
return this.lastUsedBrowserType;
|
|
}
|
|
}
|
|
//# sourceMappingURL=browser-pool.js.map
|