fix: auth scheduler env vars, concurrency and browser stability

This commit is contained in:
Giancarmine Salucci
2025-12-21 02:15:22 +01:00
parent 9357bd483a
commit 342a8eb259
9 changed files with 420 additions and 79 deletions

View File

@@ -0,0 +1,20 @@
# Outcome - Fix Auth Scheduler Env Vars
## Summary
Successfully fixed the environment variable loading issue in the authentication scheduler and updated the frequency configuration to support minutes.
## Changes
- **Refactored Scheduler Logic:**
- Updated `src/lib/server/scheduler.ts` to use `$env/dynamic/private` for reliable environment variable access.
- Changed configuration from `intervalHours` to `intervalMinutes`.
- Updated `startScheduler` to calculate interval in milliseconds based on minutes.
- **Updated Documentation:**
- Updated `src/hooks.server.ts` JSDoc to reflect the new configuration.
- **Updated Configuration:**
- Updated `.env.local` to set `AUTH_SCHEDULER_INTERVAL_MINUTES=5`.
- **Verified Tests:**
- Updated `src/tests/scheduler.spec.ts` to mock `$env/dynamic/private` and verify the new logic.
- All tests passed.
## Feature Branch
`feature/FixAuthSchedulerEnvVars`

View File

@@ -0,0 +1,21 @@
# Outcome - Fix Scheduler Concurrency and Browser Stability
## Summary
Successfully implemented fixes for the scheduler concurrency issues and browser instability.
## Changes
- **Scheduler Configuration Validation:**
- Updated `src/lib/server/scheduler.ts` to validate `intervalMinutes`.
- Added a check for `NaN` and a minimum interval of 15 minutes.
- Defaults to 720 minutes if the configuration is invalid.
- **Resource Cleanup:**
- Refactored `renewInstagramAuth` in `src/lib/server/scheduler.ts` to use a `finally` block for closing `page` and `context`.
- Ensures resources are released even if an error occurs during renewal.
- **Robust Browser Management:**
- Updated `src/lib/server/browser.ts` to check `browser.isConnected()`.
- Automatically re-initializes the browser if it is disconnected or crashed.
## Verification
- The scheduler will now default to a safe interval if misconfigured, preventing console spam.
- Browser crashes will be automatically recovered from on the next scheduler run.
- Resource leaks from failed renewal attempts are prevented.

View File

@@ -0,0 +1,89 @@
# Execution Plan: Fix Scheduler Concurrency and Browser Stability
## Context
The application is experiencing two related issues with the Instagram authentication scheduler:
1. **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., `NaN` resulting from parsing failure).
2. **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**:
1. **Validate Configuration**: In `src/lib/server/scheduler.ts`, update `getConfig()` to strictly validate `intervalMinutes`.
* Handle `NaN` (parsing errors).
* Enforce a minimum interval (e.g., 15 minutes) to prevent spamming.
* Default to 720 minutes if invalid.
2. **Improve Resource Management**: Refactor `renewInstagramAuth` to ensure `page` and `context` are closed in a `finally` block (or nested `try/finally`), preventing resource leaks if an error occurs during the renewal process.
**Verification**:
* Set `AUTH_SCHEDULER_INTERVAL_MINUTES` to an invalid value (e.g., "abc") and verify it defaults to 720.
* Verify that `setInterval` is 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**:
1. **Check Connection Status**: In `src/lib/server/browser.ts`, update `getBrowser()` to check `browser.isConnected()`.
2. **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 `isConnected` to return false).
* Verify that the next call to `getBrowser()` creates a new instance instead of throwing.
## Implementation Details
### `src/lib/server/scheduler.ts`
```typescript
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`
```typescript
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;
}
```