From 70fa984572b1a4d78bd7700b81025a7d5d0b7e3e Mon Sep 17 00:00:00 2001 From: "Tommy D. Rossi" Date: Sat, 15 Nov 2025 12:17:26 +0100 Subject: [PATCH] Create multiple-playwrights.md --- multiple-playwrights.md | 113 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 multiple-playwrights.md diff --git a/multiple-playwrights.md b/multiple-playwrights.md new file mode 100644 index 0000000..f4d3680 --- /dev/null +++ b/multiple-playwrights.md @@ -0,0 +1,113 @@ +--- +title: Multiple Playwright Clients Architecture +description: How the CDP relay server supports multiple isolated Playwright connections +prompt: | + Write a high-level architecture document explaining how the CDP relay server + was modified to support multiple Playwright clients with session isolation. + Reference: @playwriter/src/extension/cdpRelay.ts +--- + +# Multiple Playwright Clients Architecture + +The CDP relay server now supports multiple concurrent Playwright clients, each with isolated browser tab sessions. This enables parallel automation scenarios while maintaining session integrity. + +## Overview + +The relay server acts as a bridge between: +- **Multiple Playwright clients** connecting via WebSocket to `/cdp/` +- **One Chrome Extension** connecting via WebSocket to `/extension` +- **Multiple browser tabs** controlled through Chrome DevTools Protocol (CDP) + +## Client Identification + +Each Playwright client must connect with a unique identifier in the connection path: + +``` +ws://localhost:9988/cdp/client-123 +ws://localhost:9988/cdp/automation-bot-1 +ws://localhost:9988/cdp/test-runner-42 +``` + +If no client ID is provided in the path, the connection is rejected. This ensures every client can be uniquely identified and tracked. + +## Session Ownership Model + +### Tab/Session Lifecycle + +1. **Initial State**: When the Chrome Extension attaches to a browser tab, it creates a CDP session that is initially **unclaimed** +2. **Claiming Ownership**: The first Playwright client to send a command to that session **claims ownership** +3. **Exclusive Access**: Once owned, only that client can send commands to that tab/session +4. **Access Denial**: Other clients receive an error if they attempt to access an owned session +5. **Release on Disconnect**: When a client disconnects, all its owned sessions become available again + +### Example Flow + +``` +1. Extension attaches to Tab A → Session S1 created (unclaimed) +2. Client-1 sends command to S1 → Client-1 owns S1 +3. Client-2 sends command to S1 → Error: "Session S1 is owned by client-1" +4. Extension attaches to Tab B → Session S2 created (unclaimed) +5. Client-2 sends command to S2 → Client-2 owns S2 +6. Client-1 disconnects → S1 becomes unclaimed +7. Client-2 can now claim S1 if needed +``` + +## Message Routing + +### Commands (Playwright → Extension) +- Commands are tagged with the originating client ID +- Responses are routed back only to the requesting client +- Session commands validate ownership before forwarding + +### Events (Extension → Playwright) +- **Session-specific events**: Routed only to the owning client +- **Target.attachedToTarget**: Broadcast to all clients (until claimed) +- **Target.detachedFromTarget**: Sent only to the owning client +- **Global events**: Broadcast to all connected clients + +## Architecture Benefits + +### Isolation +- Each client operates independently without interference +- Prevents accidental cross-contamination of test scenarios +- Clear ownership model prevents command conflicts + +### Scalability +- Multiple test suites can run in parallel against different tabs +- Load can be distributed across multiple automation clients +- No artificial limitation on number of concurrent clients + +### Flexibility +- Clients can dynamically connect and disconnect +- Sessions can be transferred between clients (after disconnect) +- Each client can manage multiple tabs/sessions + +## Implementation Details + +The server maintains: +- `Map` - All connected Playwright clients +- `Map` - All browser sessions with ownership info +- Each `PlaywrightClient` tracks its owned sessions via `Set` + +When a command arrives with a `sessionId`, the server: +1. Checks if the session exists +2. Verifies the requesting client owns it (or claims it if unclaimed) +3. Forwards the command to the extension +4. Routes the response back to only that client + +## Use Cases + +### Parallel Test Execution +Multiple test runners can each control their own set of browser tabs without interference. + +### Monitoring & Automation Split +One client handles user automation while another monitors performance metrics on different tabs. + +### Multi-User Debugging +Multiple developers can connect their own Playwright instances to debug different parts of an application simultaneously. + +## Limitations + +- Each tab can only be controlled by one client at a time +- Session ownership is "sticky" - once claimed, it remains until client disconnect +- No built-in session sharing or handoff mechanism (by design, for safety) \ No newline at end of file