3.9 KiB
3.9 KiB
Execution Plan: Fix Scheduler Concurrency and Browser Stability
Context
The application is experiencing two related issues with the Instagram authentication scheduler:
- Console Spam: "Auth renewal already in progress" is logged repeatedly. This indicates the scheduler is triggering new renewal attempts while a previous one is still active (or perceived as active). This is likely caused by an invalid or extremely short interval configuration (e.g.,
NaNresulting from parsing failure). - Browser Instability: "Target page, context or browser has been closed" errors. This occurs when the scheduler attempts to use a cached Playwright browser instance that has crashed or disconnected.
Goal
Ensure the authentication scheduler runs reliably at the configured interval without overlapping executions, and make the browser instance management robust against crashes.
Exception to workflow
Do not create a dedicated branch. It's a fix on a new feature.
Proposed Solution
Story 1: Fix Scheduler Configuration and Resource Cleanup
Objective: Prevent rapid-fire execution of the scheduler and ensure browser resources are cleaned up properly even when errors occur.
Changes:
- Validate Configuration: In
src/lib/server/scheduler.ts, updategetConfig()to strictly validateintervalMinutes.- Handle
NaN(parsing errors). - Enforce a minimum interval (e.g., 15 minutes) to prevent spamming.
- Default to 720 minutes if invalid.
- Handle
- Improve Resource Management: Refactor
renewInstagramAuthto ensurepageandcontextare closed in afinallyblock (or nestedtry/finally), preventing resource leaks if an error occurs during the renewal process.
Verification:
- Set
AUTH_SCHEDULER_INTERVAL_MINUTESto an invalid value (e.g., "abc") and verify it defaults to 720. - Verify that
setIntervalis called with a valid duration.
Story 2: Robust Browser Lifecycle Management
Objective: Ensure the application automatically recovers from browser crashes by detecting disconnected instances.
Changes:
- Check Connection Status: In
src/lib/server/browser.ts, updategetBrowser()to checkbrowser.isConnected(). - Auto-Recovery: If the cached browser instance is not connected:
- Log a warning.
- Attempt to close the dead instance (swallowing errors).
- Re-initialize a new browser instance.
Verification:
- Simulate a browser crash (e.g., by manually killing the chrome process if possible, or mocking
isConnectedto return false). - Verify that the next call to
getBrowser()creates a new instance instead of throwing.
Implementation Details
src/lib/server/scheduler.ts
function getConfig(): SchedulerConfig {
const enabled = env.AUTH_SCHEDULER_ENABLED === 'true';
let intervalMinutes = parseInt(env.AUTH_SCHEDULER_INTERVAL_MINUTES || '720', 10);
if (isNaN(intervalMinutes) || intervalMinutes < 15) {
console.warn(`[Scheduler] Invalid or too short interval '${env.AUTH_SCHEDULER_INTERVAL_MINUTES}'. Defaulting to 720 minutes.`);
intervalMinutes = 720;
}
return { enabled, intervalMinutes };
}
// In renewInstagramAuth:
let context = null;
let page = null;
try {
// ... setup ...
context = await browser.newContext(...);
page = await context.newPage();
// ... logic ...
} catch (e) {
// ... error handling ...
} finally {
if (page) await page.close().catch(() => {});
if (context) await context.close().catch(() => {});
state.isRenewing = false;
}
src/lib/server/browser.ts
export async function getBrowser(): Promise<Browser> {
if (!browser || !browser.isConnected()) {
if (browser) {
console.warn('Browser is disconnected. Re-initializing...');
try { await browser.close(); } catch (e) { /* ignore */ }
}
return initializeBrowser();
}
return browser;
}