Session Caching Mechanism in browser-runtime.ts: How ego-lite Manages CDP Sessions with 2-Second TTL
The browser-runtime.ts module implements a lightweight session cache that retains Chrome DevTools Protocol (CDP) sessions for exactly 2 seconds, preventing redundant Target.attachToTarget calls while automatically recovering from lost connections.
The browser-runtime.ts file in the citrolabs/ego-lite repository serves as the core transport layer for browser automation, managing CDP session lifecycle through a time-based caching strategy. This session caching mechanism reduces communication overhead by reusing existing sessions within a strict 2000-millisecond window, ensuring efficient target interaction without requiring re-attachment on every operation.
Cache State Architecture
The session caching layer maintains mutable state through the centralized state object defined in package/ego-browser/src/state.ts.
State Properties for Session Management
Three critical properties track the cache condition:
sessionId: Stores the active CDP session identifier returned byTarget.attachToTargetsessionAt: Records theDate.now()timestamp of the last successful session acquisitionsessionInflight: Holds a promise that resolves to a new session while establishment is pending, preventing duplicate attachment requests
TTL Constants and Validation Logic
The 2-second cache window is enforced by the SESSION_TTL_MS constant defined at lines 5-6 of browser-runtime.ts:
const SESSION_TTL_MS = 2000;
When ensureSession() executes, it validates cache freshness through a timestamp comparison at lines 12-14:
if (state.sessionId && Date.now() - state.sessionAt < SESSION_TTL_MS) {
return state.sessionId; // ✅ Cached session still valid
}
This check determines whether to return the existing sessionId or proceed with new session establishment.
Session Acquisition Flow
The ensureSession() function (lines 7-44) orchestrates the cache logic and CDP attachment protocol.
Cache Hit Behavior
When the timestamp delta falls within the 2000ms threshold, the function immediately returns the cached identifier without network overhead. This optimization eliminates redundant Target.attachToTarget commands for rapid successive calls.
Cache Miss and Session Creation
If the cache is stale or empty, ensureSession() executes the following sequence:
- Enumerate targets via
browserEgo().listTabs()(lines 16-18) - Select a target using priority logic: preferred target, active tab, or last available tab (lines 19-23)
- Attach to target by sending the
Target.attachToTargetCDP command when the target differs from the previous session (lines 28-33) - Enable page events through
Page.enableto activate domain notifications - Update cache metadata by storing the new
sessionIdand recording the current timestamp instate.sessionAt(line 37)
Session Recovery and Invalidation
The caching mechanism includes automatic failure recovery to handle dropped CDP connections.
Detecting Session Loss
The browserCdp() function monitors request failures using the SESSION_LOST regex pattern defined at line 9. When a request returns a session-not-found error, the system recognizes the cached session as invalid.
Invalidation Strategy
Upon detecting connection loss, browserCdp() invokes invalidateSession() (lines 99-103), which:
- Clears
state.sessionIdandstate.sessionAt - Removes associated event listeners
- Forces the next
ensureSession()call to establish a fresh attachment
This recovery pattern ensures that transient network issues or target crashes do not permanently break automation workflows.
Implementation Examples
Basic Helper Usage
Helper functions automatically leverage the cache without explicit session management:
import { browserCdp } from "./browser-runtime.js";
async function clickSelector(selector: string) {
// Automatically uses cached session if <2s old
await browserCdp("Runtime.evaluate", {
expression: `document.querySelector('${selector}').click()`
});
}
Manual Cache Inspection
For debugging or advanced control, interact with the cache state directly:
import { state } from "./state.js";
import { ensureSession } from "./browser-runtime.js";
async function demoCache() {
const first = await ensureSession(); // Creates new session
console.log("First session:", first);
// Wait 1s – still within TTL
await new Promise(r => setTimeout(r, 1000));
const second = await ensureSession(); // Returns cached session
console.log("Second (cached) session:", second);
// Wait 2s – TTL expired
await new Promise(r => setTimeout(r, 2000));
const third = await ensureSession(); // Creates fresh session
console.log("Third (new) session:", third);
}
Forcing Session Refresh
Manually invalidate the cache to recover from specific error conditions:
import { invalidateSession, ensureSession } from "./browser-runtime.js";
async function recoverFromLoss() {
invalidateSession(); // Clears cache and event maps
const fresh = await ensureSession(); // Guarantees fresh attachment
console.log("Recovered session:", fresh);
}
Summary
browser-runtime.tsimplements a time-based session cache with a hardcoded 2000ms TTL viaSESSION_TTL_MS- Cache state is centralized in
state.tsthroughsessionId,sessionAt, andsessionInflightproperties ensureSession()returns cached identifiers whenDate.now() - state.sessionAt < 2000, avoiding redundantTarget.attachToTargetcalls- Automatic recovery occurs through
invalidateSession()when theSESSION_LOSTregex detects disconnected sessions - Concurrent safety is maintained via
sessionInflightpromises that prevent duplicate attachment attempts during cache misses
Frequently Asked Questions
What triggers a session cache miss in browser-runtime.ts?
A cache miss occurs when state.sessionId is undefined, state.sessionAt is undefined, or when Date.now() - state.sessionAt equals or exceeds SESSION_TTL_MS (2000ms). Additionally, explicit calls to invalidateSession() or detection of a lost session through the SESSION_LOST error pattern immediately clear the cache and force a new attachment.
How does the 2-second TTL impact browser automation performance?
The 2-second window balances connection reuse against stale session detection. According to the citrolabs/ego-lite source code, this TTL reduces CDP attachment overhead for rapid successive operations—such as multi-step form interactions—while ensuring that automation recovers quickly from target crashes or navigation events that invalidate existing sessions.
Can the session TTL be configured or disabled?
No, SESSION_TTL_MS is defined as a constant at lines 5-6 of browser-runtime.ts with a fixed value of 2000ms. The repository does not expose configuration options for this parameter, as the 2-second duration is optimized for the typical lifecycle of browser automation tasks while preventing resource leaks from abandoned CDP sessions.
How does session recovery work after a Target.detachFromTarget event?
When browserCdp() encounters a "session lost" error matching the SESSION_LOST regex, it automatically invokes invalidateSession() (lines 99-103). This function clears state.sessionId and state.sessionAt, then forces the next CDP request to trigger ensureSession() and establish a fresh Target.attachToTarget connection. This recovery mechanism operates transparently without requiring manual intervention in helper functions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →