good stuff

This commit is contained in:
Andras Schmelczer 2026-03-15 21:10:54 +00:00
parent ea8389ef40
commit f4de0eeb9f
39 changed files with 5165 additions and 348 deletions

View file

@ -50,6 +50,10 @@ export class ScreenshotCache {
normalized.tab = params.get('tab')!;
}
if (params.get('og')) {
normalized.og = params.get('og')!;
}
if (params.get('path')) {
normalized.path = params.get('path')!;
}

View file

@ -180,29 +180,49 @@ async function releasePage(page: Page): Promise<void> {
* Pre-warm the browser and populate the network cache by loading the app once.
* Subsequent screenshots benefit from cached JS/CSS bundles, map tiles,
* and V8 compiled bytecode eliminating cold-start latency.
*
* Retries with exponential backoff if the frontend isn't up yet (common during
* docker-compose startup where the frontend may still be installing/building).
*/
export async function initialize(appUrl: string): Promise<void> {
console.log('Pre-warming browser and caches...');
const page = await createPage();
try {
await page.goto(`${appUrl}/?screenshot=1`, {
waitUntil: 'load',
timeout: 30_000,
});
// Wait for the app to fully load and cache all resources
const MAX_RETRIES = 10;
const INITIAL_DELAY_MS = 2_000;
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
const page = await createPage();
try {
await page.waitForFunction('window.__screenshot_ready === true', {
timeout: READY_TIMEOUT,
await page.goto(`${appUrl}/?screenshot=1`, {
waitUntil: 'load',
timeout: 30_000,
});
} catch {
// Non-fatal — cache will still have JS/CSS/tiles from the partial load
// Wait for the app to fully load and cache all resources
try {
await page.waitForFunction('window.__screenshot_ready === true', {
timeout: READY_TIMEOUT,
});
} catch {
// Non-fatal — cache will still have JS/CSS/tiles from the partial load
}
console.log(`Pre-warm complete. Cache: ${networkCache.stats()}`);
await page.close().catch(() => {});
await warmPool();
return;
} catch (err) {
await page.close().catch(() => {});
if (attempt === MAX_RETRIES) {
console.warn(`Pre-warm failed after ${MAX_RETRIES} attempts (non-fatal):`, err);
} else {
const delay = INITIAL_DELAY_MS * Math.pow(2, attempt - 1);
console.log(`Pre-warm attempt ${attempt}/${MAX_RETRIES} failed, retrying in ${(delay / 1000).toFixed(0)}s...`);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
console.log(`Pre-warm complete. Cache: ${networkCache.stats()}`);
} catch (err) {
console.warn('Pre-warm failed (non-fatal):', err);
} finally {
await page.close().catch(() => {});
}
// Even if pre-warm failed, still warm the page pool so first real
// screenshot requests don't pay for page creation
await warmPool();
}