From 0e2e8d1766838785a158eaf709bf0cf8f564f869 Mon Sep 17 00:00:00 2001 From: mariosemes Date: Thu, 26 Mar 2026 22:42:15 +0100 Subject: [PATCH] Pre-launch Chromium on server startup to avoid cold-start blocking Chromium cold launch takes several seconds and blocks the event loop, preventing SSE events from flushing. Now the browser is warmed up during server startup if any store uses render_js, so the first search doesn't pay the launch penalty. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/server/index.ts | 8 ++++++++ src/server/scraper/browser-scraper.ts | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/server/index.ts b/src/server/index.ts index 0bebeb2..28a596e 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -7,6 +7,8 @@ import { config } from './config.js'; import { initDatabase, startAutoSave, saveDatabase } from './db/connection.js'; import { runMigrations } from './db/migrate.js'; import { syncFromFiles } from './services/store-sync.js'; +import { warmupBrowser } from './scraper/browser-scraper.js'; +import { getEnabledStores } from './models/store.js'; import { storeRoutes } from './routes/stores.js'; import { categoryRoutes } from './routes/categories.js'; import { searchRoutes } from './routes/search.js'; @@ -63,6 +65,12 @@ if (sync.errors.length > 0) { startAutoSave(); +// Pre-launch Chromium if any store needs JS rendering +const hasJsStores = getEnabledStores().some((s) => s.render_js); +if (hasJsStores) { + warmupBrowser().catch((err) => app.log.warn(`Browser warmup failed: ${err}`)); +} + // Save database on shutdown process.on('SIGINT', () => { saveDatabase(); process.exit(0); }); process.on('SIGTERM', () => { saveDatabase(); process.exit(0); }); diff --git a/src/server/scraper/browser-scraper.ts b/src/server/scraper/browser-scraper.ts index c581eb0..9badc4a 100644 --- a/src/server/scraper/browser-scraper.ts +++ b/src/server/scraper/browser-scraper.ts @@ -116,6 +116,12 @@ export async function scrapeStoreWithBrowser(store: Store, searchUrl: string): P } } +export async function warmupBrowser(): Promise { + log('Warming up browser...'); + await getBrowser(); + log('Browser ready'); +} + export async function closeBrowser(): Promise { if (browser) { await browser.close();