fix(workspace url): race condition

This commit is contained in:
Vikhyath Mondreti
2025-06-27 16:35:55 -07:00
parent bf9b3fdc99
commit bbde2be093
5 changed files with 62 additions and 21 deletions

View File

@@ -861,7 +861,28 @@ const WorkflowContent = React.memo(() => {
// Navigate to existing workflow or first available
if (!workflows[currentId]) {
logger.info(`Workflow ${currentId} not found, redirecting to first available workflow`)
router.replace(`/workspace/${workspaceId}/w/${workflowIds[0]}`)
// Validate that workflows belong to the current workspace before redirecting
const workspaceWorkflows = workflowIds.filter(id => {
const workflow = workflows[id]
return workflow.workspaceId === workspaceId
})
if (workspaceWorkflows.length > 0) {
router.replace(`/workspace/${workspaceId}/w/${workspaceWorkflows[0]}`)
} else {
// No valid workflows for this workspace, redirect to workspace root
router.replace(`/workspace/${workspaceId}/w`)
}
return
}
// Validate that the current workflow belongs to the current workspace
const currentWorkflow = workflows[currentId]
if (currentWorkflow && currentWorkflow.workspaceId !== workspaceId) {
logger.warn(`Workflow ${currentId} belongs to workspace ${currentWorkflow.workspaceId}, not ${workspaceId}`)
// Redirect to the correct workspace for this workflow
router.replace(`/workspace/${currentWorkflow.workspaceId}/w/${currentId}`)
return
}

View File

@@ -1,36 +1,56 @@
'use client'
import { useEffect } from 'react'
import { useEffect, useState } from 'react'
import { useParams, useRouter } from 'next/navigation'
import { LoadingAgent } from '@/components/ui/loading-agent'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
export default function WorkflowsPage() {
const router = useRouter()
const { workflows, isLoading } = useWorkflowRegistry()
const { workflows, isLoading, loadWorkflows } = useWorkflowRegistry()
const [hasInitialized, setHasInitialized] = useState(false)
const params = useParams()
const workspaceId = params.workspaceId
const workspaceId = params.workspaceId as string
// Initialize workspace workflows
useEffect(() => {
// Wait for workflows to load
if (isLoading) return
const initializeWorkspace = async () => {
try {
await loadWorkflows(workspaceId)
setHasInitialized(true)
} catch (error) {
console.error('Failed to load workflows for workspace:', error)
setHasInitialized(true) // Still mark as initialized to show error state
}
}
if (!hasInitialized) {
initializeWorkspace()
}
}, [workspaceId, loadWorkflows, hasInitialized])
// Handle redirection once workflows are loaded
useEffect(() => {
// Only proceed if we've initialized and workflows are not loading
if (!hasInitialized || isLoading) return
const workflowIds = Object.keys(workflows)
// If we have workflows, redirect to the first one
if (workflowIds.length > 0) {
router.replace(`/workspace/${workspaceId}/w/${workflowIds[0]}`)
return
// Validate that workflows belong to the current workspace
const workspaceWorkflows = workflowIds.filter(id => {
const workflow = workflows[id]
return workflow.workspaceId === workspaceId
})
// If we have valid workspace workflows, redirect to the first one
if (workspaceWorkflows.length > 0) {
router.replace(`/workspace/${workspaceId}/w/${workspaceWorkflows[0]}`)
}
}, [hasInitialized, isLoading, workflows, workspaceId, router])
// If no workflows exist after loading is complete, this means the workspace creation
// didn't work properly or the user doesn't have any workspaces.
// Redirect to home to let the system handle workspace/workflow creation properly.
router.replace('/')
}, [workflows, isLoading, router, workspaceId])
// Show loading state while determining where to redirect
// Always show loading state until redirect happens
// There should always be a default workflow, so we never show "no workflows found"
return (
<div className='flex h-screen items-center justify-center'>
<div className='text-center'>

View File

@@ -26,8 +26,8 @@ const connectionString = env.POSTGRES_URL ?? env.DATABASE_URL
const postgresClient = postgres(connectionString, {
prepare: false, // Disable prefetch as it is not supported for "Transaction" pool mode
idle_timeout: 20, // Reduce idle timeout to 20 seconds to free up connections faster
connect_timeout: 10, // Reduce connect timeout to 10 seconds
max: 3, // Conservative limit - with multiple serverless functions, this prevents pool exhaustion
connect_timeout: 30, // Increase connect timeout to 30 seconds to handle network issues
max: 2, // Further reduced limit to prevent Supabase connection exhaustion
onnotice: () => {}, // Disable notices to reduce noise
})

View File

@@ -15,7 +15,7 @@ const socketDb = drizzle(
postgres(connectionString, {
prepare: false,
idle_timeout: 10, // Shorter idle timeout for socket operations
connect_timeout: 5, // Faster connection timeout
connect_timeout: 20, // Increase connection timeout for socket operations
max: 2, // Very small pool for socket server to avoid exhausting Supabase limit
onnotice: () => {}, // Disable notices
debug: false, // Disable debug for socket operations

View File

@@ -13,7 +13,7 @@ const db = drizzle(
postgres(connectionString, {
prepare: false,
idle_timeout: 15,
connect_timeout: 5,
connect_timeout: 20, // Increase connection timeout for room operations
max: 1, // Minimal pool for room operations to conserve connections
onnotice: () => {},
}),