mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-17 18:25:42 +02:00
[eric] crash-safety: cap parallel CDP detach at 10 concurrent (unbounded could flood the debugger host at pathological card counts and leave one attached at unmount)
This commit is contained in:
@@ -39,14 +39,23 @@ export async function removeBrowserCardCleanly(
|
||||
dispatch(removeBrowserCard(browserId));
|
||||
}
|
||||
|
||||
// Batch remove: detach every browser's CDP in PARALLEL (order-independent, the only invariant is
|
||||
// all debuggers gone before any unmount), THEN remove them. Serial detach cost ~72ms/browser, so a
|
||||
// 20-card multi-select delete lagged over a second; this keeps the crash-safe ordering but flat.
|
||||
// Detach many browsers' CDP concurrently but CAPPED (order-independent, the only invariant is all
|
||||
// debuggers gone before any unmount). Serial cost ~72ms/browser (a 20-card teardown lagged >1s);
|
||||
// unbounded parallel risks flooding the debugger host at pathological counts and leaving one
|
||||
// attached at unmount. Batches of DETACH_CONCURRENCY are the middle: flat-ish latency, no flood.
|
||||
const DETACH_CONCURRENCY = 10;
|
||||
export async function detachBrowsersCdpBounded(browserIds: string[]): Promise<void> {
|
||||
for (let i = 0; i < browserIds.length; i += DETACH_CONCURRENCY) {
|
||||
await Promise.allSettled(browserIds.slice(i, i + DETACH_CONCURRENCY).map((id) => detachBrowserCdp(id)));
|
||||
}
|
||||
}
|
||||
|
||||
// Batch remove: bounded-parallel detach, THEN remove. Keeps the crash-safe ordering but flat.
|
||||
export async function removeBrowserCardsCleanly(
|
||||
browserIds: string[],
|
||||
dispatch: Dispatch,
|
||||
): Promise<void> {
|
||||
await Promise.allSettled(browserIds.map((id) => detachBrowserCdp(id)));
|
||||
await detachBrowsersCdpBounded(browserIds);
|
||||
for (const id of browserIds) {
|
||||
forgetBrowser(id);
|
||||
dispatch(removeBrowserCard(id));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { getAllViewOutputIds } from '@/shared/viewWebviewRegistry';
|
||||
import { getAllBrowserIds } from '@/shared/browserRegistry';
|
||||
import { quiesceViewWebview } from '@/shared/viewTeardown';
|
||||
import { detachBrowserCdp } from '@/shared/browserTeardown';
|
||||
import { detachBrowsersCdpBounded } from '@/shared/browserTeardown';
|
||||
|
||||
// Switching dashboards clears every card from the store in ONE reducer (resetLayout), so React
|
||||
// unmounts all the outgoing app + browser <webview>s in a single frame. Ripping several live GPU
|
||||
@@ -20,7 +20,5 @@ export async function prepareDashboardSwitch(keepBrowserIds: string[]): Promise<
|
||||
for (const outputId of getAllViewOutputIds()) {
|
||||
await quiesceViewWebview(outputId);
|
||||
}
|
||||
await Promise.allSettled(
|
||||
getAllBrowserIds().filter((b) => !keep.has(b)).map((b) => detachBrowserCdp(b)),
|
||||
);
|
||||
await detachBrowsersCdpBounded(getAllBrowserIds().filter((b) => !keep.has(b)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user