feat: launch a lazy per-run browser for the fallback scraper

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gwc3aCiyQxmCWQke8RvEz
This commit is contained in:
Sjoerd de Vries
2026-09-05 17:39:03 +02:00
parent 358347e8ba
commit fc8dadc8a3
+34 -14
View File
@@ -8,6 +8,7 @@ const {
recordCheckSuccess, recordCheckFailure, recordCheckSuccess, recordCheckFailure,
} = require('./src/db'); } = require('./src/db');
const { fetchAndExtractPrice } = require('./src/scraper'); const { fetchAndExtractPrice } = require('./src/scraper');
const { launchBrowser, fetchAndExtractPriceViaBrowser } = require('./src/browserScraper');
const { createTransport, sendPriceChangeEmail } = require('./src/mailer'); const { createTransport, sendPriceChangeEmail } = require('./src/mailer');
const { checkAllProducts } = require('./src/checkProducts'); const { checkAllProducts } = require('./src/checkProducts');
const { start: startScheduler } = require('./src/scheduler'); const { start: startScheduler } = require('./src/scheduler');
@@ -36,23 +37,42 @@ function summarize(results) {
return parts.length > 0 ? parts.join(' ') : 'geen producten'; return parts.length > 0 ? parts.join(' ') : 'geen producten';
} }
function runCheck() { async function runCheck() {
const products = listProducts(db); const products = listProducts(db);
const deps = { let browserPromise = null;
fetchAndExtractPrice, function getBrowser() {
sendMail: (payload) => sendPriceChangeEmail(transport, { if (!browserPromise) {
from: process.env.SMTP_FROM, browserPromise = launchBrowser();
to: process.env.NOTIFY_EMAIL, }
...payload, return browserPromise;
}), }
recordCheckFailure: (id, status) => recordCheckFailure(db, id, status), try {
recordCheckSuccess: (id, data) => recordCheckSuccess(db, id, data), const deps = {
now: () => new Date().toISOString(), fetchAndExtractPrice,
}; fetchAndExtractPriceViaBrowser: async (url) => {
return checkAllProducts(products, deps).then((results) => { const browser = await getBrowser();
return fetchAndExtractPriceViaBrowser(browser, url);
},
sendMail: (payload) => sendPriceChangeEmail(transport, {
from: process.env.SMTP_FROM,
to: process.env.NOTIFY_EMAIL,
...payload,
}),
recordCheckFailure: (id, status) => recordCheckFailure(db, id, status),
recordCheckSuccess: (id, data) => recordCheckSuccess(db, id, data),
now: () => new Date().toISOString(),
};
const results = await checkAllProducts(products, deps);
console.log(`[check] ${products.length} product(en) gecontroleerd: ${summarize(results)}`); console.log(`[check] ${products.length} product(en) gecontroleerd: ${summarize(results)}`);
return results; return results;
}); } finally {
if (browserPromise) {
const browser = await browserPromise;
await browser.close().catch((err) => {
console.error(`[check] kon de browser niet netjes sluiten: ${err && err.message}`);
});
}
}
} }
startScheduler(runCheck); startScheduler(runCheck);