From 8ff8d0a684a2cdc532900e57b913bf84e0050e22 Mon Sep 17 00:00:00 2001 From: Rohit Date: Tue, 3 Jun 2025 18:56:58 +0530 Subject: [PATCH] feat: add fallback dummy socket run logic --- server/src/browser-management/controller.ts | 113 +++++++++++++++++--- 1 file changed, 100 insertions(+), 13 deletions(-) diff --git a/server/src/browser-management/controller.ts b/server/src/browser-management/controller.ts index b020f711..0589b68c 100644 --- a/server/src/browser-management/controller.ts +++ b/server/src/browser-management/controller.ts @@ -54,20 +54,23 @@ export const initializeRemoteBrowserForRecording = (userId: string): string => { * @category BrowserManagement-Controller */ export const createRemoteBrowserForRun = (userId: string): string => { - const id = uuid(); + if (!userId) { + logger.log('error', 'createRemoteBrowserForRun: Missing required parameter userId'); + throw new Error('userId is required'); + } + + const id = uuid(); + + const slotReserved = browserPool.reserveBrowserSlot(id, userId, "run"); + if (!slotReserved) { + logger.log('warn', `Cannot create browser for user ${userId}: no available slots`); + throw new Error('User has reached maximum browser limit'); + } + + logger.log('info', `createRemoteBrowserForRun: Reserved slot ${id} for user ${userId}`); + + initializeBrowserAsync(id, userId); - createSocketConnectionForRun( - io.of(id), - async (socket: Socket) => { - try { - const browserSession = new RemoteBrowser(socket, userId, id); - await browserSession.initialize(userId); - browserPool.addRemoteBrowser(id, browserSession, userId, false, "run"); - socket.emit('ready-for-run'); - } catch (error: any) { - logger.error(`Error initializing browser: ${error.message}`); - } - }); return id; }; @@ -211,3 +214,87 @@ export const stopRunningInterpretation = async (userId: string) => { logger.log('error', 'Cannot stop interpretation: No active browser or generator.'); } }; + +const initializeBrowserAsync = async (id: string, userId: string) => { + try { + const namespace = io.of(id); + let clientConnected = false; + let connectionTimeout: NodeJS.Timeout; + + const waitForConnection = new Promise((resolve) => { + namespace.on('connection', (socket: Socket) => { + clientConnected = true; + clearTimeout(connectionTimeout); + logger.log('info', `Frontend connected to browser ${id} via socket ${socket.id}`); + resolve(socket); + }); + + connectionTimeout = setTimeout(() => { + if (!clientConnected) { + logger.log('warn', `No client connected to browser ${id} within timeout, proceeding with dummy socket`); + resolve(null); + } + }, 10000); + }); + + namespace.on('error', (error: any) => { + logger.log('error', `Socket namespace error for browser ${id}: ${error.message}`); + clearTimeout(connectionTimeout); + browserPool.failBrowserSlot(id); + }); + + const socket = await waitForConnection; + + try { + let browserSession: RemoteBrowser; + + if (socket) { + logger.log('info', `Using real socket for browser ${id}`); + browserSession = new RemoteBrowser(socket, userId, id); + } else { + logger.log('info', `Using dummy socket for browser ${id}`); + const dummySocket = { + emit: (event: string, data?: any) => { + logger.log('debug', `Browser ${id} dummy socket emitted ${event}:`, data); + }, + on: () => {}, + id: `dummy-${id}`, + } as any; + + browserSession = new RemoteBrowser(dummySocket, userId, id); + } + + await browserSession.initialize(userId); + + const upgraded = browserPool.upgradeBrowserSlot(id, browserSession); + if (!upgraded) { + throw new Error('Failed to upgrade reserved browser slot'); + } + + if (socket) { + socket.emit('ready-for-run'); + } else { + setTimeout(async () => { + try { + logger.log('info', `Starting execution for browser ${id} with dummy socket`); + } catch (error: any) { + logger.log('error', `Error executing run for browser ${id}: ${error.message}`); + } + }, 100); + } + + logger.log('info', `Browser ${id} successfully initialized for run with ${socket ? 'real' : 'dummy'} socket`); + + } catch (error: any) { + logger.log('error', `Error initializing browser ${id}: ${error.message}`); + browserPool.failBrowserSlot(id); + if (socket) { + socket.emit('error', { message: error.message }); + } + } + + } catch (error: any) { + logger.log('error', `Error setting up browser ${id}: ${error.message}`); + browserPool.failBrowserSlot(id); + } +};