feat: Iteration node support parallel mode (#9493)
This commit is contained in:
@@ -60,36 +60,67 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe
|
||||
}, [notify, getResultCallback])
|
||||
|
||||
const formatNodeList = useCallback((list: NodeTracing[]) => {
|
||||
const allItems = list.reverse()
|
||||
const allItems = [...list].reverse()
|
||||
const result: NodeTracing[] = []
|
||||
allItems.forEach((item) => {
|
||||
const { node_type, execution_metadata } = item
|
||||
if (node_type !== BlockEnum.Iteration) {
|
||||
const isInIteration = !!execution_metadata?.iteration_id
|
||||
const groupMap = new Map<string, NodeTracing[]>()
|
||||
|
||||
if (isInIteration) {
|
||||
const iterationNode = result.find(node => node.node_id === execution_metadata?.iteration_id)
|
||||
const iterationDetails = iterationNode?.details
|
||||
const currentIterationIndex = execution_metadata?.iteration_index ?? 0
|
||||
|
||||
if (Array.isArray(iterationDetails)) {
|
||||
if (iterationDetails.length === 0 || !iterationDetails[currentIterationIndex])
|
||||
iterationDetails[currentIterationIndex] = [item]
|
||||
else
|
||||
iterationDetails[currentIterationIndex].push(item)
|
||||
}
|
||||
return
|
||||
}
|
||||
// not in iteration
|
||||
result.push(item)
|
||||
|
||||
return
|
||||
}
|
||||
const processIterationNode = (item: NodeTracing) => {
|
||||
result.push({
|
||||
...item,
|
||||
details: [],
|
||||
})
|
||||
}
|
||||
const updateParallelModeGroup = (runId: string, item: NodeTracing, iterationNode: NodeTracing) => {
|
||||
if (!groupMap.has(runId))
|
||||
groupMap.set(runId, [item])
|
||||
else
|
||||
groupMap.get(runId)!.push(item)
|
||||
if (item.status === 'failed') {
|
||||
iterationNode.status = 'failed'
|
||||
iterationNode.error = item.error
|
||||
}
|
||||
|
||||
iterationNode.details = Array.from(groupMap.values())
|
||||
}
|
||||
const updateSequentialModeGroup = (index: number, item: NodeTracing, iterationNode: NodeTracing) => {
|
||||
const { details } = iterationNode
|
||||
if (details) {
|
||||
if (!details[index])
|
||||
details[index] = [item]
|
||||
else
|
||||
details[index].push(item)
|
||||
}
|
||||
|
||||
if (item.status === 'failed') {
|
||||
iterationNode.status = 'failed'
|
||||
iterationNode.error = item.error
|
||||
}
|
||||
}
|
||||
const processNonIterationNode = (item: NodeTracing) => {
|
||||
const { execution_metadata } = item
|
||||
if (!execution_metadata?.iteration_id) {
|
||||
result.push(item)
|
||||
return
|
||||
}
|
||||
|
||||
const iterationNode = result.find(node => node.node_id === execution_metadata.iteration_id)
|
||||
if (!iterationNode || !Array.isArray(iterationNode.details))
|
||||
return
|
||||
|
||||
const { parallel_mode_run_id, iteration_index = 0 } = execution_metadata
|
||||
|
||||
if (parallel_mode_run_id)
|
||||
updateParallelModeGroup(parallel_mode_run_id, item, iterationNode)
|
||||
else
|
||||
updateSequentialModeGroup(iteration_index, item, iterationNode)
|
||||
}
|
||||
|
||||
allItems.forEach((item) => {
|
||||
item.node_type === BlockEnum.Iteration
|
||||
? processIterationNode(item)
|
||||
: processNonIterationNode(item)
|
||||
})
|
||||
|
||||
return result
|
||||
}, [])
|
||||
|
||||
|
@@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiArrowRightSLine,
|
||||
RiCloseLine,
|
||||
RiErrorWarningLine,
|
||||
} from '@remixicon/react'
|
||||
import { ArrowNarrowLeft } from '../../base/icons/src/vender/line/arrows'
|
||||
import TracingPanel from './tracing-panel'
|
||||
@@ -27,7 +28,7 @@ const IterationResultPanel: FC<Props> = ({
|
||||
noWrap,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const [expandedIterations, setExpandedIterations] = useState<Record<number, boolean>>([])
|
||||
const [expandedIterations, setExpandedIterations] = useState<Record<number, boolean>>({})
|
||||
|
||||
const toggleIteration = useCallback((index: number) => {
|
||||
setExpandedIterations(prev => ({
|
||||
@@ -71,10 +72,19 @@ const IterationResultPanel: FC<Props> = ({
|
||||
<span className='system-sm-semibold-uppercase text-text-primary flex-grow'>
|
||||
{t(`${i18nPrefix}.iteration`)} {index + 1}
|
||||
</span>
|
||||
<RiArrowRightSLine className={cn(
|
||||
'w-4 h-4 text-text-tertiary transition-transform duration-200 flex-shrink-0',
|
||||
expandedIterations[index] && 'transform rotate-90',
|
||||
)} />
|
||||
{
|
||||
iteration.some(item => item.status === 'failed')
|
||||
? (
|
||||
<RiErrorWarningLine className='w-4 h-4 text-text-destructive' />
|
||||
)
|
||||
: (< RiArrowRightSLine className={
|
||||
cn(
|
||||
'w-4 h-4 text-text-tertiary transition-transform duration-200 flex-shrink-0',
|
||||
expandedIterations[index] && 'transform rotate-90',
|
||||
)} />
|
||||
)
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{expandedIterations[index] && <div
|
||||
|
@@ -72,7 +72,16 @@ const NodePanel: FC<Props> = ({
|
||||
|
||||
return iteration_length
|
||||
}
|
||||
const getErrorCount = (details: NodeTracing[][] | undefined) => {
|
||||
if (!details || details.length === 0)
|
||||
return 0
|
||||
|
||||
return details.reduce((acc, iteration) => {
|
||||
if (iteration.some(item => item.status === 'failed'))
|
||||
acc++
|
||||
return acc
|
||||
}, 0)
|
||||
}
|
||||
useEffect(() => {
|
||||
setCollapseState(!nodeInfo.expand)
|
||||
}, [nodeInfo.expand, setCollapseState])
|
||||
@@ -136,7 +145,12 @@ const NodePanel: FC<Props> = ({
|
||||
onClick={handleOnShowIterationDetail}
|
||||
>
|
||||
<Iteration className='w-4 h-4 text-components-button-tertiary-text flex-shrink-0' />
|
||||
<div className='flex-1 text-left system-sm-medium text-components-button-tertiary-text'>{t('workflow.nodes.iteration.iteration', { count: getCount(nodeInfo.details?.length, nodeInfo.metadata?.iterator_length) })}</div>
|
||||
<div className='flex-1 text-left system-sm-medium text-components-button-tertiary-text'>{t('workflow.nodes.iteration.iteration', { count: getCount(nodeInfo.details?.length, nodeInfo.metadata?.iterator_length) })}{getErrorCount(nodeInfo.details) > 0 && (
|
||||
<>
|
||||
{t('workflow.nodes.iteration.comma')}
|
||||
{t('workflow.nodes.iteration.error', { count: getErrorCount(nodeInfo.details) })}
|
||||
</>
|
||||
)}</div>
|
||||
{justShowIterationNavArrow
|
||||
? (
|
||||
<RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text flex-shrink-0' />
|
||||
|
Reference in New Issue
Block a user