Reboot assetImage browser when it disappears
Been seeing this in testing in prod, the first few images worked great, but then eventually they all started saying the browser was disconnected. Here, we add a check to reconnect if it goes missing. This is actually kinda hard to test in dev, because the dev server creates a new process every time the function runs, so fingers crossed! I also added explicit logic to close the page when we're done with it, I'm worried we crashed the browser by exceeding the RAM limit by leaving pages open. Not sure quite how their model works and whether things eventually get flushed out on their own!
This commit is contained in:
parent
f036890aa1
commit
fc52439387
1 changed files with 32 additions and 20 deletions
|
@ -37,6 +37,13 @@ const ASSET_IMAGE_PAGE_BASE_URL = process.env.VERCEL_URL
|
||||||
// parallel will be a problem for our API endpoint.
|
// parallel will be a problem for our API endpoint.
|
||||||
let BROWSER;
|
let BROWSER;
|
||||||
async function getBrowser() {
|
async function getBrowser() {
|
||||||
|
// Sometimes, the browser crashes. Maybe a RAM thing? If that happened, set
|
||||||
|
// it to null, and then we'll replace it with a new instance below.
|
||||||
|
if (BROWSER && !BROWSER.isConnected()) {
|
||||||
|
console.info("Browser is no longer connected; rebooting.");
|
||||||
|
BROWSER = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!BROWSER) {
|
if (!BROWSER) {
|
||||||
if (process.env["NODE_ENV"] === "production") {
|
if (process.env["NODE_ENV"] === "production") {
|
||||||
// In production, we use a special chrome-aws-lambda Chromium.
|
// In production, we use a special chrome-aws-lambda Chromium.
|
||||||
|
@ -102,28 +109,33 @@ async function loadAndScreenshotImage(libraryUrl, size) {
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
console.debug("Page opened, navigating to: " + assetImagePageUrl.toString());
|
console.debug("Page opened, navigating to: " + assetImagePageUrl.toString());
|
||||||
|
|
||||||
await page.goto(assetImagePageUrl.toString());
|
try {
|
||||||
console.debug("Page loaded, awaiting image");
|
await page.goto(assetImagePageUrl.toString());
|
||||||
|
console.debug("Page loaded, awaiting image");
|
||||||
|
|
||||||
// Start looking for the loaded canvas, *and* for an error message.
|
// Start looking for the loaded canvas, *and* for an error message.
|
||||||
// When either one displays, we proceed, either by returning the image if
|
// When either one displays, we proceed, either by returning the image if
|
||||||
// present, or raising the error if present.
|
// present, or raising the error if present.
|
||||||
const imageBufferPromise = screenshotImageFromPage(page);
|
const imageBufferPromise = screenshotImageFromPage(page);
|
||||||
const errorMessagePromise = readErrorMessageFromPage(page);
|
const errorMessagePromise = readErrorMessageFromPage(page);
|
||||||
const firstResultFromPage = await Promise.any([
|
const firstResultFromPage = await Promise.any([
|
||||||
imageBufferPromise.then((imageBuffer) => ({ imageBuffer })),
|
imageBufferPromise.then((imageBuffer) => ({ imageBuffer })),
|
||||||
errorMessagePromise.then((errorMessage) => ({ errorMessage })),
|
errorMessagePromise.then((errorMessage) => ({ errorMessage })),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (firstResultFromPage.errorMessage) {
|
if (firstResultFromPage.errorMessage) {
|
||||||
throw new Error(firstResultFromPage.errorMessage);
|
throw new Error(firstResultFromPage.errorMessage);
|
||||||
} else if (firstResultFromPage.imageBuffer) {
|
} else if (firstResultFromPage.imageBuffer) {
|
||||||
return firstResultFromPage.imageBuffer;
|
return firstResultFromPage.imageBuffer;
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Assertion error: Promise.any did not return an errorMessage or an imageBuffer: ` +
|
`Assertion error: Promise.any did not return an errorMessage or an imageBuffer: ` +
|
||||||
`${JSON.stringify(Object.keys(firstResultFromPage))}`
|
`${JSON.stringify(Object.keys(firstResultFromPage))}`
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// Close the page, to save on RAM in our shared browser instance.
|
||||||
|
page.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue