Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(deploy): address PR review feedback
- Remove redundant isLoading check (subset of isPending in RQ v5)
- Make deployedState prop nullable to avoid non-null assertion
- Destructure mutateAsync to eliminate ESLint suppression
- Guard debounced invalidation against stale workflowId on switch
  • Loading branch information
waleedlatif1 committed Mar 16, 2026
commit b6a225583633e302d49f4f4142d908ce4abc3fac
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const logger = createLogger('GeneralDeploy')

interface GeneralDeployProps {
workflowId: string | null
deployedState: WorkflowState
deployedState?: WorkflowState | null
isLoadingDeployedState: boolean
versions: WorkflowDeploymentVersionResponse[]
versionsLoading: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ interface DeployModalProps {
workflowId: string | null
isDeployed: boolean
needsRedeployment: boolean
deployedState: WorkflowState
deployedState?: WorkflowState | null
isLoadingDeployedState: boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export function Deploy({ activeWorkflowId, userPermissions, className }: DeployP
workflowId={activeWorkflowId}
isDeployed={isDeployed}
needsRedeployment={changeDetected}
deployedState={deployedState!}
deployedState={deployedState}
isLoadingDeployedState={isLoadingDeployedState}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ export function useChangeDetection({
// Track initial lastSaved to detect saves after load.
// Debounced to avoid redundant API calls during rapid auto-saves.
const initialLastSavedRef = useRef<number | undefined>(undefined)
const workflowIdRef = useRef(workflowId)

// Reset tracking when workflow changes — must run before the lastSaved effect
// to prevent spurious invalidation with a stale ref during workflow switches.
useEffect(() => {
workflowIdRef.current = workflowId
initialLastSavedRef.current = undefined
}, [workflowId])

useEffect(() => {
if (lastSaved !== undefined && initialLastSavedRef.current === undefined) {
Expand All @@ -76,20 +84,17 @@ export function useChangeDetection({

initialLastSavedRef.current = lastSaved

const capturedWorkflowId = workflowId
const timer = setTimeout(() => {
if (workflowIdRef.current !== capturedWorkflowId) return
queryClient.invalidateQueries({
queryKey: deploymentKeys.info(workflowId),
queryKey: deploymentKeys.info(capturedWorkflowId),
})
}, 500)

return () => clearTimeout(timer)
}, [lastSaved, workflowId, queryClient])

// Reset tracking when workflow changes
useEffect(() => {
initialLastSavedRef.current = undefined
}, [workflowId])

// Skip expensive state merge when server result is available (the common path).
// Only build currentState for the client-side fallback comparison.
const needsClientFallback = serverNeedsRedeployment === undefined && !isServerLoading
Expand All @@ -106,7 +111,16 @@ export function useChangeDetection({
parallels,
variables: workflowVariables,
} as WorkflowState & { variables: Record<string, any> }
}, [needsClientFallback, workflowId, blocks, edges, loops, parallels, subBlockValues, workflowVariables])
}, [
needsClientFallback,
workflowId,
blocks,
edges,
loops,
parallels,
subBlockValues,
workflowVariables,
])

const changeDetected = useMemo(() => {
if (isServerLoading) return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,8 @@ interface UseDeploymentProps {
* First deploy: runs pre-deploy checks, then deploys via mutation and opens modal.
* Already deployed: opens modal directly (validation happens on Update in modal).
*/
export function useDeployment({
workflowId,
isDeployed,
}: UseDeploymentProps) {
const deployMutation = useDeployWorkflow()
export function useDeployment({ workflowId, isDeployed }: UseDeploymentProps) {
const { mutateAsync, isPending: isDeploying } = useDeployWorkflow()
const addNotification = useNotificationStore((state) => state.addNotification)

const handleDeployClick = useCallback(async () => {
Expand Down Expand Up @@ -48,7 +45,7 @@ export function useDeployment({
}

try {
await deployMutation.mutateAsync({ workflowId, deployChatEnabled: false })
await mutateAsync({ workflowId, deployChatEnabled: false })
return { success: true, shouldOpenModal: true }
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Failed to deploy workflow'
Expand All @@ -59,11 +56,10 @@ export function useDeployment({
})
return { success: false, shouldOpenModal: false }
}
// eslint-disable-next-line react-hooks/exhaustive-deps -- mutateAsync is a stable reference
}, [workflowId, isDeployed, addNotification])
}, [workflowId, isDeployed, addNotification, mutateAsync])

return {
isDeploying: deployMutation.isPending,
isDeploying,
handleDeployClick,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ export function useChildWorkflow(
}
}

const { data, isLoading, isPending } = useDeploymentInfo(
const { data, isPending } = useDeploymentInfo(
isWorkflowSelector ? (childWorkflowId ?? null) : null
)

const childIsDeployed = data?.isDeployed ?? null
const childNeedsRedeploy = data?.needsRedeployment ?? false
const isLoadingChildVersion = isLoading || isPending
const isLoadingChildVersion = isPending

return {
childWorkflowId,
Expand Down
Loading