mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 10:27:09 +00:00
111 lines
3.2 KiB
JavaScript
111 lines
3.2 KiB
JavaScript
const path = require('path');
|
|
const fs = require('fs');
|
|
const { Builder, By, Key, until } = require('selenium-webdriver');
|
|
const firefox = require('selenium-webdriver/firefox');
|
|
const { execSync } = require('child_process');
|
|
|
|
const geckodriverPath = path.resolve(__dirname, "geckodriver");
|
|
|
|
// State to prevent race conditions
|
|
let driver = null;
|
|
let timer = null;
|
|
let isShuttingDown = false;
|
|
|
|
// Verify GeckoDriver exists
|
|
if (!fs.existsSync(geckodriverPath)) {
|
|
throw new Error(`GeckoDriver not found at ${geckodriverPath}`);
|
|
}
|
|
|
|
function resetTimer() {
|
|
clearTimeout(timer);
|
|
timer = setTimeout(shutdown, 120000); // 2 minutes inactivity timeout
|
|
}
|
|
|
|
async function launch() {
|
|
if (isShuttingDown) {
|
|
console.log("Shutdown in progress, waiting...");
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
return launch(); // Retry after delay
|
|
}
|
|
resetTimer();
|
|
if (!driver) {
|
|
console.log("Launching Firefox");
|
|
const options = new firefox.Options();
|
|
// Explicitly set headless mode and optimize for server
|
|
options.addArguments('--headless', '--no-sandbox', '--disable-gpu');
|
|
// Limit content processes to reduce resource usage
|
|
options.setPreference('dom.ipc.processCount', 1);
|
|
|
|
const service = new firefox.ServiceBuilder(geckodriverPath);
|
|
driver = await new Builder()
|
|
.forBrowser('firefox')
|
|
.setFirefoxService(service)
|
|
.setFirefoxOptions(options)
|
|
.build();
|
|
}
|
|
}
|
|
|
|
async function shutdown() {
|
|
if (driver && !isShuttingDown) {
|
|
isShuttingDown = true;
|
|
console.log("Shutting down Firefox");
|
|
try {
|
|
const d = driver;
|
|
driver = null;
|
|
await d.quit();
|
|
// Explicitly stop the service
|
|
const service = d.service;
|
|
if (service) {
|
|
service.stop();
|
|
}
|
|
console.log("Firefox shutdown complete");
|
|
} catch (error) {
|
|
console.error("Error during shutdown:", error);
|
|
// Forcefully kill lingering processes (Linux/Unix)
|
|
try {
|
|
execSync('pkill -u $USER firefox || true');
|
|
execSync('pkill -u $USER geckodriver || true');
|
|
console.log("Terminated lingering Firefox/GeckoDriver processes");
|
|
} catch (killError) {
|
|
console.error("Error killing processes:", killError);
|
|
}
|
|
} finally {
|
|
isShuttingDown = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function url2pdf(url) {
|
|
await launch();
|
|
try {
|
|
console.log(`Navigating to ${url}`);
|
|
await driver.get(url);
|
|
// Add delay to stabilize Marionette communication
|
|
await driver.sleep(3000);
|
|
const pdf = await driver.printPage({ width: 21.0, height: 29.7 });
|
|
resetTimer(); // Reset timer after successful operation
|
|
return pdf;
|
|
} catch (error) {
|
|
console.error("Error in url2pdf:", error);
|
|
await shutdown(); // Force shutdown on error
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Periodically clean up orphaned processes (every 5 minutes)
|
|
setInterval(() => {
|
|
try {
|
|
const firefoxCount = execSync('pgrep -c firefox || echo 0').toString().trim();
|
|
if (parseInt(firefoxCount) > 0 && !driver) {
|
|
console.log(`Found ${firefoxCount} orphaned Firefox processes, cleaning up...`);
|
|
execSync('pkill -u $USER firefox || true');
|
|
execSync('pkill -u $USER geckodriver || true');
|
|
console.log("Cleaned up orphaned processes");
|
|
}
|
|
} catch (error) {
|
|
console.error("Error checking orphaned processes:", error);
|
|
}
|
|
}, 300000);
|
|
|
|
module.exports = { url2pdf };
|