How ensureSession() Works in ego-lite: CDP Session Management Explained
The ensureSession() function in citrolabs/ego-lite guarantees a valid Chrome DevTools Protocol (CDP) session by validating cached sessions against a TTL, deduplicating concurrent attach requests, discovering active browser tabs, and initializing page event listeners before returning a session identifier.
The ensureSession() function serves as the foundational gatekeeper for all browser-level operations in ego-lite, an open-source browser automation framework. Before any CDP command executes, this helper validates connection state to ensure seamless interaction with the embedded Chrome instance. According to the source code in package/ego-browser/src/browser-runtime.ts, the function implements an eight-stage lifecycle that balances performance caching with connection reliability.
The Eight-Stage Session Lifecycle
The implementation spans lines 107-140 of browser-runtime.ts, executing atomically through the following phases:
-
Cache Validation – If
state.sessionIdexists andDate.now() - state.sessionAt < SESSION_TTL_MS, the function returns the cached identifier immediately, avoiding unnecessary re-attachment overhead. -
In-Flight Deduplication – When multiple callers request sessions simultaneously, the first caller creates a promise stored in
state.sessionInflight. Subsequent callers return this same promise, ensuring only one attach sequence runs concurrently. -
Tab Discovery – The function invokes
browserEgo().listTabs()to retrieve current target information. It prioritizesstate.preferredTargetIdif set, otherwise selects the first active tab, falling back to the last available tab. -
Tab Validation – If no active tab is discovered, the function throws an explicit error:
"no active tab to attach session", preventing silent failures downstream. -
Session Attachment – When the discovered
targetIddiffers fromstate.sessionTargetIdor no session exists, the function callsTarget.attachToTargetto establish a new CDP session, storing the returnedsessionId. -
Event Initialization – Immediately after attachment,
enablePageEvents(state.sessionId)registers listeners for page-level CDP events including DOM updates and console messages. -
Timestamp Refresh – The function updates
state.sessionAt = Date.now()to reset the TTL clock for subsequent cache checks. -
Cleanup – Regardless of success or failure, the
finallyblock clearsstate.sessionInflight = null, allowing future calls to initiate new attach sequences.
Source Code Architecture
In package/ego-browser/src/browser-runtime.ts, the ensureSession() function interacts with mutable state managed in package/ego-browser/src/state.ts. The state object tracks sessionId, sessionAt, sessionInflight, preferredTargetId, and sessionTargetId across the application lifecycle.
The function distinguishes between browser-level operations and page-level commands through the BROWSER_LEVEL(method) check. Unless operating at browser scope, higher-level helpers like cdp() and js() automatically invoke ensureSession() before transmitting commands, making session management transparent to end users.
Practical Usage Examples
Direct session retrieval leverages the caching mechanism for optimal performance:
import { ensureSession } from 'ego-browser';
// Obtain a cached session ID valid for SESSION_TTL_MS
const sessionId = await ensureSession();
console.log('Active CDP session:', sessionId);
Higher-level helpers implicitly manage sessions during CDP execution:
import { cdp } from 'ego-browser';
// Runtime.evaluate automatically triggers ensureSession()
const result = await cdp('Runtime.evaluate', {
expression: 'document.title'
});
console.log('Page title:', result.result.value);
Concurrent calls demonstrate the deduplication logic:
// Both calls share the same attach promise
const [s1, s2] = await Promise.all([
ensureSession(),
ensureSession()
]);
console.log(s1 === s2); // true - single attachment performed
Force re-attachment after navigation invalidates the current tab:
import { invalidateSession, ensureSession } from 'ego-browser';
await invalidateSession(); // Clears cached state
const freshId = await ensureSession(); // Re-attaches to current active tab
Supporting Files and Dependencies
The session management ecosystem spans multiple modules:
package/ego-browser/src/state.ts– Maintains runtime mutable state including session timestamps and inflight promises.package/ego-browser/src/cdp-eval.ts– Exportscdp()andjs()wrappers that depend onensureSession()for non-browser-level operations.package/ego-browser/src/driver/– Navigation, screencast, and download drivers invokeensureSession()before issuing protocol commands.package/ego-browser/src/browser-runtime.test.mjs– Validates caching behavior, TTL expiration, concurrent deduplication, and tab selection logic.
Summary
ensureSession()validates cached CDP sessions againstSESSION_TTL_MSbefore initiating expensive attach operations.- Concurrent deduplication prevents redundant attachment attempts when multiple async callers request sessions simultaneously.
- Tab selection logic prioritizes preferred targets, then active tabs, falling back to the last available tab to ensure connection stability.
- Automatic lifecycle management enables event listeners and state cleanup without manual intervention, supporting transparent operation through higher-level APIs like
cdp()andjs().
Frequently Asked Questions
What triggers ensureSession() to attach a new session instead of using the cache?
The function attaches a new session when the cached session ID is missing, the TTL has expired (Date.now() - state.sessionAt >= SESSION_TTL_MS), or when the current target ID differs from state.sessionTargetId. This ensures the CDP session always matches the active browser tab after navigation or context switches.
How does ensureSession() handle multiple simultaneous calls?
When ensureSession() receives concurrent requests while no valid session exists, the first call creates a promise stored in state.sessionInflight. Subsequent calls detect this promise and return it immediately, ensuring only one Target.attachToTarget operation executes despite multiple callers.
What happens if no browser tabs are available when ensureSession() runs?
If browserEgo().listTabs() returns an empty list or no active tab is found, the function throws new Error("no active tab to attach session") at lines 123-125 of browser-runtime.ts. This explicit failure prevents undefined behavior in downstream CDP operations.
Can I force ensureSession() to bypass the cache and create a fresh session?
While ensureSession() itself does not accept parameters to bypass caching, you can invalidate the current session by calling invalidateSession(), which clears state.sessionId and state.sessionTargetId. The next call to ensureSession() will then execute a fresh attach sequence to the current active tab.
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 →