Skip to content

Commit fd7ea59

Browse files
waleedlatif1claude
andcommitted
fix(logs): final-audit follow-ups — stable tab callback, byExecution invalidation, optimistic detail patch, trace loading state
- Wrap LogDetails -> LogDetailsContent onActiveTabChange in useCallback so the child useEffect doesn't refire on every parent render. - Add logKeys.byExecutionAll() to cancel + retry invalidation so the table-embedded sidebar picks up status changes immediately. - Optimistic write-through to logKeys.detail in useCancelExecution so the open sidebar reflects 'cancelling' instantly; rolls back on error. - Distinguish trace loading from trace-empty: when log.executionData is not yet fetched, render "Loading trace…" instead of the empty state. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 824f00a commit fd7ea59

2 files changed

Lines changed: 40 additions & 13 deletions

File tree

apps/sim/app/workspace/[workspaceId]/logs/components/log-details/log-details.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { memo, useEffect, useMemo, useRef, useState } from 'react'
3+
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
44
import { formatDuration } from '@sim/utils/formatting'
55
import { ArrowDown, ArrowUp, Check, ChevronUp, Clipboard, Eye, Search, X } from 'lucide-react'
66
import { createPortal } from 'react-dom'
@@ -600,12 +600,18 @@ export function LogDetailsContent({ log, onActiveTabChange }: LogDetailsContentP
600600
>
601601
{traceSpans?.length ? (
602602
<TraceView traceSpans={traceSpans} />
603-
) : (
603+
) : log.executionData ? (
604604
<div className='flex h-full items-center justify-center px-4 text-center'>
605605
<span className='font-medium text-[var(--text-tertiary)] text-sm'>
606606
No trace data available for this run
607607
</span>
608608
</div>
609+
) : (
610+
<div className='flex h-full items-center justify-center px-4 text-center'>
611+
<span className='font-medium text-[var(--text-tertiary)] text-sm'>
612+
Loading trace…
613+
</span>
614+
</div>
609615
)}
610616
</SModalTabsContent>
611617
)}
@@ -667,6 +673,14 @@ export const LogDetails = memo(function LogDetails({
667673
}: LogDetailsProps) {
668674
const activeTabRef = useRef<LogDetailsTab>('overview')
669675

676+
const handleActiveTabChange = useCallback(
677+
(tab: LogDetailsTab) => {
678+
activeTabRef.current = tab
679+
onActiveTabChange?.(tab)
680+
},
681+
[onActiveTabChange]
682+
)
683+
670684
const panelWidth = useLogDetailsUIStore((state) => state.panelWidth)
671685
const { handleMouseDown } = useLogDetailsResize()
672686

@@ -773,13 +787,7 @@ export const LogDetails = memo(function LogDetails({
773787
</div>
774788
</div>
775789

776-
<LogDetailsContent
777-
log={log}
778-
onActiveTabChange={(tab) => {
779-
activeTabRef.current = tab
780-
onActiveTabChange?.(tab)
781-
}}
782-
/>
790+
<LogDetailsContent log={log} onActiveTabChange={handleActiveTabChange} />
783791
</div>
784792
)}
785793
</div>

apps/sim/hooks/queries/logs.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,29 +323,47 @@ export function useCancelExecution() {
323323
queryKey: logKeys.lists(),
324324
})
325325

326+
let affectedLogId: string | null = null
326327
queryClient.setQueriesData<InfiniteData<LogsPage>>({ queryKey: logKeys.lists() }, (old) => {
327328
if (!old) return old
328329
return {
329330
...old,
330331
pages: old.pages.map((page) => ({
331332
...page,
332-
logs: page.logs.map((log) =>
333-
log.executionId === executionId ? { ...log, status: 'cancelling' } : log
334-
),
333+
logs: page.logs.map((log) => {
334+
if (log.executionId !== executionId) return log
335+
affectedLogId = log.id
336+
return { ...log, status: 'cancelling' }
337+
}),
335338
})),
336339
}
337340
})
338341

339-
return { previousQueries }
342+
let previousDetail: WorkflowLog | undefined
343+
if (affectedLogId) {
344+
previousDetail = queryClient.getQueryData<WorkflowLog>(logKeys.detail(affectedLogId))
345+
if (previousDetail) {
346+
queryClient.setQueryData<WorkflowLog>(logKeys.detail(affectedLogId), {
347+
...previousDetail,
348+
status: 'cancelling',
349+
})
350+
}
351+
}
352+
353+
return { previousQueries, affectedLogId, previousDetail }
340354
},
341355
onError: (_err, _variables, context) => {
342356
for (const [queryKey, data] of context?.previousQueries ?? []) {
343357
queryClient.setQueryData(queryKey, data)
344358
}
359+
if (context?.affectedLogId && context.previousDetail !== undefined) {
360+
queryClient.setQueryData(logKeys.detail(context.affectedLogId), context.previousDetail)
361+
}
345362
},
346363
onSettled: () => {
347364
queryClient.invalidateQueries({ queryKey: logKeys.lists() })
348365
queryClient.invalidateQueries({ queryKey: logKeys.details() })
366+
queryClient.invalidateQueries({ queryKey: logKeys.byExecutionAll() })
349367
queryClient.invalidateQueries({ queryKey: logKeys.stats() })
350368
},
351369
})
@@ -375,6 +393,7 @@ export function useRetryExecution() {
375393
onSettled: () => {
376394
queryClient.invalidateQueries({ queryKey: logKeys.lists() })
377395
queryClient.invalidateQueries({ queryKey: logKeys.details() })
396+
queryClient.invalidateQueries({ queryKey: logKeys.byExecutionAll() })
378397
queryClient.invalidateQueries({ queryKey: logKeys.stats() })
379398
},
380399
})

0 commit comments

Comments
 (0)