Merge pull request #551 from simstudioai/improvement/socket-per-session

Improvement(socket conn level): move socket connection to browser session level rather than workspace
This commit is contained in:
Vikhyath Mondreti
2025-06-26 08:40:11 -07:00
committed by GitHub
3 changed files with 44 additions and 31 deletions

View File

@@ -1,18 +1,15 @@
import { WorkspaceProvider } from '@/providers/workspace-provider'
import Providers from './w/components/providers/providers'
import { Sidebar } from './w/components/sidebar/sidebar'
export default function WorkspaceLayout({ children }: { children: React.ReactNode }) {
return (
<WorkspaceProvider>
<Providers>
<div className='flex min-h-screen w-full'>
<div className='z-20'>
<Sidebar />
</div>
<div className='flex flex-1 flex-col'>{children}</div>
<Providers>
<div className='flex min-h-screen w-full'>
<div className='z-20'>
<Sidebar />
</div>
</Providers>
</WorkspaceProvider>
<div className='flex flex-1 flex-col'>{children}</div>
</div>
</Providers>
)
}

View File

@@ -0,0 +1,22 @@
'use client'
import { useSession } from '@/lib/auth-client'
import { SocketProvider } from '@/contexts/socket-context'
interface WorkspaceRootLayoutProps {
children: React.ReactNode
}
export default function WorkspaceRootLayout({ children }: WorkspaceRootLayoutProps) {
const session = useSession()
const user = session.data?.user
? {
id: session.data.user.id,
name: session.data.user.name,
email: session.data.user.email,
}
: undefined
return <SocketProvider user={user}>{children}</SocketProvider>
}

View File

@@ -99,21 +99,13 @@ export function SocketProvider({ children, user }: SocketProviderProps) {
workflowDeleted?: (data: any) => void
}>({})
// Initialize socket when user is available
// Initialize socket when user is available - only once per session
useEffect(() => {
if (!user?.id) return
// Prevent duplicate connections - disconnect existing socket first
if (socket) {
logger.info('Disconnecting existing socket before creating new one')
socket.disconnect()
setSocket(null)
setIsConnected(false)
}
// Prevent multiple simultaneous initialization attempts
if (isConnecting) {
logger.info('Socket initialization already in progress, skipping')
// Only initialize if we don't have a socket and aren't already connecting
if (socket || isConnecting) {
logger.info('Socket already exists or is connecting, skipping initialization')
return
}
@@ -296,16 +288,8 @@ export function SocketProvider({ children, user }: SocketProviderProps) {
// Start the socket initialization
initializeSocket()
// Cleanup on unmount or user change
// Cleanup on unmount only (not on user change since socket is session-level)
return () => {
if (socket) {
logger.info('Cleaning up socket connection')
socket.disconnect()
setSocket(null)
setIsConnected(false)
setIsConnecting(false)
}
positionUpdateTimeouts.current.forEach((timeoutId) => {
clearTimeout(timeoutId)
})
@@ -314,6 +298,16 @@ export function SocketProvider({ children, user }: SocketProviderProps) {
}
}, [user?.id])
// Cleanup socket on component unmount
useEffect(() => {
return () => {
if (socket) {
logger.info('Cleaning up socket connection on unmount')
socket.disconnect()
}
}
}, [])
// Join workflow room
const joinWorkflow = useCallback(
(workflowId: string) => {