Create a new browser for each assetImage request

Well, holding onto the browser instance seems to be a source of bugs (my previous fix didn't seem to fix it), and I'm not _sure_ what the perf characteristics are, so let's just try a fresh instance each time!

I don't actually know what a browser "instance" in Playwright really is, I'm not sure it even necessarily creates a new process, I just don't know

and I saw some Vercel example code take this approach, which is definitely simpler, and I guess must not be _overtly_ bad perf if it's idiomatic?

So, like, ok, cool, let's see if this stops 500ing us with "Browser closed"! 😅
This commit is contained in:
Emi Matchu 2021-09-02 19:25:48 -07:00
parent 781034a568
commit ea8791c69d

View file

@ -30,26 +30,16 @@ const ASSET_IMAGE_PAGE_BASE_URL = process.env.VERCEL_URL
? "http://localhost:3000/internal/assetImage" ? "http://localhost:3000/internal/assetImage"
: "https://impress-2020.openneo.net/internal/assetImage"; : "https://impress-2020.openneo.net/internal/assetImage";
// TODO: What are the perf implications of sharing one browser instance, with // TODO: We used to share a browser instamce, but we couldn't get it to reload
// multiple pages open? This feels optimal to me from the *obvious* // correctly after accidental closes, so we're just gonna always load a
// perspective, but I do wonder whether e.g. there are surprise // new one now. What are the perf implications of this? Does it slow down
// implications from sharing a browser instance, or if too many pages in // response time substantially?
// parallel will be a problem for our API endpoint.
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 (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.
const chromium = require("chrome-aws-lambda"); const chromium = require("chrome-aws-lambda");
const playwright = require("playwright-core"); const playwright = require("playwright-core");
BROWSER = await playwright.chromium.launch({ return await playwright.chromium.launch({
args: chromium.args, args: chromium.args,
executablePath: await chromium.executablePath, executablePath: await chromium.executablePath,
headless: true, headless: true,
@ -57,11 +47,9 @@ async function getBrowser() {
} else { } else {
// In development, we use the standard playwright Chromium. // In development, we use the standard playwright Chromium.
const playwright = require("playwright"); const playwright = require("playwright");
BROWSER = await playwright.chromium.launch({ headless: true }); return await playwright.chromium.launch({ headless: true });
} }
} }
return BROWSER;
}
async function handle(req, res) { async function handle(req, res) {
const { libraryUrl, size } = req.query; const { libraryUrl, size } = req.query;