mirror of
https://github.com/jo-inc/camofox-browser.git
synced 2026-10-02 04:14:41 +08:00
Recycle wedged idle browsers sooner
This commit is contained in:
@@ -38,6 +38,6 @@ primary_region = "sjc"
|
||||
[env]
|
||||
NODE_ENV = "production"
|
||||
SESSION_TIMEOUT_MS = "600000"
|
||||
BROWSER_IDLE_TIMEOUT_MS = "3900000"
|
||||
BROWSER_IDLE_TIMEOUT_MS = "900000"
|
||||
MAX_SESSIONS = "10"
|
||||
MAX_OLD_SPACE_SIZE = "512"
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
import crypto from 'crypto';
|
||||
import { monitorEventLoopDelay } from 'perf_hooks';
|
||||
import { collectResourceSnapshot, classifyProxyError, browserProcessTreeRssMb } from './resources.js';
|
||||
import { collectResourceSnapshot, classifyProxyError, browserProcessTreeRssMb, browserProcessNameRssMb } from './resources.js';
|
||||
|
||||
// ============================================================================
|
||||
// Anonymization
|
||||
@@ -434,7 +434,7 @@ export function createTabHealthTracker(page) {
|
||||
// collectResourceSnapshot and classifyProxyError live in lib/resources.js
|
||||
// (isolated from network code for clean separation of concerns).
|
||||
// Re-exported here for backward compatibility.
|
||||
export { collectResourceSnapshot, classifyProxyError, browserProcessTreeRssMb };
|
||||
export { collectResourceSnapshot, classifyProxyError, browserProcessTreeRssMb, browserProcessNameRssMb };
|
||||
|
||||
// ============================================================================
|
||||
// Rate limiter (sliding window, 1 hour)
|
||||
|
||||
@@ -55,6 +55,48 @@ export function browserProcessTreeRssMb(browserPid) {
|
||||
return Math.round(totalKb / 1024);
|
||||
}
|
||||
|
||||
const BROWSER_PROCESS_NAMES = new Set([
|
||||
'camoufox-bin',
|
||||
'firefox',
|
||||
'Web Content',
|
||||
'WebExtensions',
|
||||
'Socket Process',
|
||||
'Utility Process',
|
||||
'RDD Process',
|
||||
'Privileged Cont',
|
||||
]);
|
||||
|
||||
function readProcessName(pid) {
|
||||
const comm = fs.readFileSync(`/proc/${pid}/comm`, 'utf8').trim();
|
||||
if (comm) return comm;
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallback browser RSS scanner for Camoufox/Firefox. Playwright's browser.process()
|
||||
* can be unavailable depending on the launcher path, but the process names are
|
||||
* still visible in /proc inside the Fly machine.
|
||||
*/
|
||||
export function browserProcessNameRssMb() {
|
||||
if (process.platform !== 'linux') return null;
|
||||
let totalKb = 0;
|
||||
let found = false;
|
||||
|
||||
for (const pid of fs.readdirSync('/proc')) {
|
||||
if (!/^\d+$/.test(pid)) continue;
|
||||
try {
|
||||
const name = readProcessName(pid);
|
||||
if (!BROWSER_PROCESS_NAMES.has(name)) continue;
|
||||
totalKb += readVmRssKb(pid);
|
||||
found = true;
|
||||
} catch {
|
||||
// Process exited or /proc access failed; skip it.
|
||||
}
|
||||
}
|
||||
|
||||
return found ? Math.round(totalKb / 1024) : null;
|
||||
}
|
||||
|
||||
export function collectResourceSnapshot(opts = {}) {
|
||||
const mem = process.memoryUsage();
|
||||
const snap = {
|
||||
|
||||
@@ -33,7 +33,7 @@ import {
|
||||
import { actionFromReq, classifyError } from './lib/request-utils.js';
|
||||
import { cleanupOrphanedTempFiles, cleanupStaleFirefoxProfiles } from './lib/tmp-cleanup.js';
|
||||
import { coalesceInflight } from './lib/inflight.js';
|
||||
import { createReporter, createTabHealthTracker, collectResourceSnapshot, classifyProxyError, browserProcessTreeRssMb } from './lib/reporter.js';
|
||||
import { createReporter, createTabHealthTracker, collectResourceSnapshot, classifyProxyError, browserProcessTreeRssMb, browserProcessNameRssMb } from './lib/reporter.js';
|
||||
import { mountDocs } from './lib/openapi.js';
|
||||
import { initSentry, captureException as sentryCaptureException, setupExpressErrorHandler as setupSentryErrorHandler, flush as sentryFlush } from './lib/sentry.js';
|
||||
import { prepareExternalCamoufoxExecutable } from './lib/camoufox-executable.js';
|
||||
@@ -5150,7 +5150,7 @@ setInterval(() => {
|
||||
if (sessions.size > 0 || !browser) return;
|
||||
const mem = process.memoryUsage();
|
||||
const nativeMemMb = Math.round((mem.rss - mem.heapUsed) / 1048576);
|
||||
const browserRssMb = browserProcessTreeRssMb(_browserPid());
|
||||
const browserRssMb = browserProcessTreeRssMb(_browserPid()) ?? browserProcessNameRssMb();
|
||||
|
||||
if (browserRssMb !== null && browserRssMb >= CONFIG.browserRssRestartThresholdMb) {
|
||||
log('warn', 'browser rss pressure, restarting browser', {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { describe, expect, test } from '@jest/globals';
|
||||
import { browserProcessNameRssMb } from '../../lib/resources.js';
|
||||
|
||||
describe('browserProcessNameRssMb', () => {
|
||||
test('returns null on non-linux platforms or no browser processes', () => {
|
||||
const value = browserProcessNameRssMb();
|
||||
expect(value === null || Number.isInteger(value)).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user