mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-14 10:35:51 +08:00
Fix/workflow retry (#11999)
This commit is contained in:
parent
e068bbec73
commit
ef95b1268e
@ -387,6 +387,9 @@ export const useWorkflowRun = () => {
|
|||||||
if (nodeIndex !== -1) {
|
if (nodeIndex !== -1) {
|
||||||
currIteration[nodeIndex] = {
|
currIteration[nodeIndex] = {
|
||||||
...currIteration[nodeIndex],
|
...currIteration[nodeIndex],
|
||||||
|
...(currIteration[nodeIndex].retryDetail
|
||||||
|
? { retryDetail: currIteration[nodeIndex].retryDetail }
|
||||||
|
: {}),
|
||||||
...data,
|
...data,
|
||||||
} as any
|
} as any
|
||||||
}
|
}
|
||||||
@ -626,6 +629,8 @@ export const useWorkflowRun = () => {
|
|||||||
const {
|
const {
|
||||||
workflowRunningData,
|
workflowRunningData,
|
||||||
setWorkflowRunningData,
|
setWorkflowRunningData,
|
||||||
|
iterParallelLogMap,
|
||||||
|
setIterParallelLogMap,
|
||||||
} = workflowStore.getState()
|
} = workflowStore.getState()
|
||||||
const {
|
const {
|
||||||
getNodes,
|
getNodes,
|
||||||
@ -633,6 +638,52 @@ export const useWorkflowRun = () => {
|
|||||||
} = store.getState()
|
} = store.getState()
|
||||||
|
|
||||||
const nodes = getNodes()
|
const nodes = getNodes()
|
||||||
|
const currentNode = nodes.find(node => node.id === data.node_id)!
|
||||||
|
const nodeParent = nodes.find(node => node.id === currentNode.parentId)
|
||||||
|
if (nodeParent) {
|
||||||
|
if (!data.execution_metadata.parallel_mode_run_id) {
|
||||||
|
setWorkflowRunningData(produce(workflowRunningData!, (draft) => {
|
||||||
|
const tracing = draft.tracing!
|
||||||
|
const iteration = tracing.find(trace => trace.node_id === nodeParent.id)
|
||||||
|
|
||||||
|
if (iteration && iteration.details?.length) {
|
||||||
|
const currentNodeRetry = iteration.details[nodeParent.data._iterationIndex - 1]?.find(item => item.node_id === data.node_id)
|
||||||
|
|
||||||
|
if (currentNodeRetry) {
|
||||||
|
if (currentNodeRetry?.retryDetail)
|
||||||
|
currentNodeRetry?.retryDetail.push(data as NodeTracing)
|
||||||
|
else
|
||||||
|
currentNodeRetry.retryDetail = [data as NodeTracing]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setWorkflowRunningData(produce(workflowRunningData!, (draft) => {
|
||||||
|
const tracing = draft.tracing!
|
||||||
|
const iteration = tracing.find(trace => trace.node_id === nodeParent.id)
|
||||||
|
|
||||||
|
if (iteration && iteration.details?.length) {
|
||||||
|
const iterRunID = data.execution_metadata?.parallel_mode_run_id
|
||||||
|
|
||||||
|
const currIteration = iterParallelLogMap.get(iteration.node_id)?.get(iterRunID)
|
||||||
|
const currentNodeRetry = currIteration?.find(item => item.node_id === data.node_id)
|
||||||
|
|
||||||
|
if (currentNodeRetry) {
|
||||||
|
if (currentNodeRetry?.retryDetail)
|
||||||
|
currentNodeRetry?.retryDetail.push(data as NodeTracing)
|
||||||
|
else
|
||||||
|
currentNodeRetry.retryDetail = [data as NodeTracing]
|
||||||
|
}
|
||||||
|
setIterParallelLogMap(iterParallelLogMap)
|
||||||
|
const iterLogMap = iterParallelLogMap.get(iteration.node_id)
|
||||||
|
if (iterLogMap)
|
||||||
|
iteration.details = Array.from(iterLogMap.values())
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
setWorkflowRunningData(produce(workflowRunningData!, (draft) => {
|
setWorkflowRunningData(produce(workflowRunningData!, (draft) => {
|
||||||
const tracing = draft.tracing!
|
const tracing = draft.tracing!
|
||||||
const currentRetryNodeIndex = tracing.findIndex(trace => trace.node_id === data.node_id)
|
const currentRetryNodeIndex = tracing.findIndex(trace => trace.node_id === data.node_id)
|
||||||
@ -641,11 +692,11 @@ export const useWorkflowRun = () => {
|
|||||||
const currentRetryNode = tracing[currentRetryNodeIndex]
|
const currentRetryNode = tracing[currentRetryNodeIndex]
|
||||||
if (currentRetryNode.retryDetail)
|
if (currentRetryNode.retryDetail)
|
||||||
draft.tracing![currentRetryNodeIndex].retryDetail!.push(data as NodeTracing)
|
draft.tracing![currentRetryNodeIndex].retryDetail!.push(data as NodeTracing)
|
||||||
|
|
||||||
else
|
else
|
||||||
draft.tracing![currentRetryNodeIndex].retryDetail = [data as NodeTracing]
|
draft.tracing![currentRetryNodeIndex].retryDetail = [data as NodeTracing]
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
}
|
||||||
const newNodes = produce(nodes, (draft) => {
|
const newNodes = produce(nodes, (draft) => {
|
||||||
const currentNode = draft.find(node => node.id === data.node_id)!
|
const currentNode = draft.find(node => node.id === data.node_id)!
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ const RetryOnNode = ({
|
|||||||
}, [data._runningStatus, showSelectedBorder])
|
}, [data._runningStatus, showSelectedBorder])
|
||||||
const showDefault = !isRunning && !isSuccessful && !isException && !isFailed
|
const showDefault = !isRunning && !isSuccessful && !isException && !isFailed
|
||||||
|
|
||||||
if (!retry_config)
|
if (!retry_config?.retry_enabled)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -74,7 +74,7 @@ const RetryOnNode = ({
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
!showDefault && (
|
!showDefault && !!data._retryIndex && (
|
||||||
<div>
|
<div>
|
||||||
{data._retryIndex}/{data.retry_config?.max_retries}
|
{data._retryIndex}/{data.retry_config?.max_retries}
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,11 +78,24 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe
|
|||||||
|
|
||||||
const groupMap = nodeGroupMap.get(iterationNode.node_id)!
|
const groupMap = nodeGroupMap.get(iterationNode.node_id)!
|
||||||
|
|
||||||
if (!groupMap.has(runId))
|
if (!groupMap.has(runId)) {
|
||||||
groupMap.set(runId, [item])
|
groupMap.set(runId, [item])
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (item.status === 'retry') {
|
||||||
|
const retryNode = groupMap.get(runId)!.find(node => node.node_id === item.node_id)
|
||||||
|
|
||||||
|
if (retryNode) {
|
||||||
|
if (retryNode?.retryDetail)
|
||||||
|
retryNode.retryDetail.push(item)
|
||||||
else
|
else
|
||||||
|
retryNode.retryDetail = [item]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
groupMap.get(runId)!.push(item)
|
groupMap.get(runId)!.push(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (item.status === 'failed') {
|
if (item.status === 'failed') {
|
||||||
iterationNode.status = 'failed'
|
iterationNode.status = 'failed'
|
||||||
@ -94,11 +107,25 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe
|
|||||||
const updateSequentialModeGroup = (index: number, item: NodeTracing, iterationNode: NodeTracing) => {
|
const updateSequentialModeGroup = (index: number, item: NodeTracing, iterationNode: NodeTracing) => {
|
||||||
const { details } = iterationNode
|
const { details } = iterationNode
|
||||||
if (details) {
|
if (details) {
|
||||||
if (!details[index])
|
if (!details[index]) {
|
||||||
details[index] = [item]
|
details[index] = [item]
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (item.status === 'retry') {
|
||||||
|
const retryNode = details[index].find(node => node.node_id === item.node_id)
|
||||||
|
|
||||||
|
if (retryNode) {
|
||||||
|
if (retryNode?.retryDetail)
|
||||||
|
retryNode.retryDetail.push(item)
|
||||||
else
|
else
|
||||||
|
retryNode.retryDetail = [item]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
details[index].push(item)
|
details[index].push(item)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (item.status === 'failed') {
|
if (item.status === 'failed') {
|
||||||
iterationNode.status = 'failed'
|
iterationNode.status = 'failed'
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
import { ArrowNarrowLeft } from '../../base/icons/src/vender/line/arrows'
|
import { ArrowNarrowLeft } from '../../base/icons/src/vender/line/arrows'
|
||||||
import { NodeRunningStatus } from '../types'
|
import { NodeRunningStatus } from '../types'
|
||||||
import TracingPanel from './tracing-panel'
|
import TracingPanel from './tracing-panel'
|
||||||
|
import RetryResultPanel from './retry-result-panel'
|
||||||
import { Iteration } from '@/app/components/base/icons/src/vender/workflow'
|
import { Iteration } from '@/app/components/base/icons/src/vender/workflow'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
import type { IterationDurationMap, NodeTracing } from '@/types/workflow'
|
import type { IterationDurationMap, NodeTracing } from '@/types/workflow'
|
||||||
@ -41,8 +42,8 @@ const IterationResultPanel: FC<Props> = ({
|
|||||||
}))
|
}))
|
||||||
}, [])
|
}, [])
|
||||||
const countIterDuration = (iteration: NodeTracing[], iterDurationMap: IterationDurationMap): string => {
|
const countIterDuration = (iteration: NodeTracing[], iterDurationMap: IterationDurationMap): string => {
|
||||||
const IterRunIndex = iteration[0].execution_metadata.iteration_index as number
|
const IterRunIndex = iteration[0]?.execution_metadata?.iteration_index as number
|
||||||
const iterRunId = iteration[0].execution_metadata.parallel_mode_run_id
|
const iterRunId = iteration[0]?.execution_metadata?.parallel_mode_run_id
|
||||||
const iterItem = iterDurationMap[iterRunId || IterRunIndex]
|
const iterItem = iterDurationMap[iterRunId || IterRunIndex]
|
||||||
const duration = iterItem
|
const duration = iterItem
|
||||||
return `${(duration && duration > 0.01) ? duration.toFixed(2) : 0.01}s`
|
return `${(duration && duration > 0.01) ? duration.toFixed(2) : 0.01}s`
|
||||||
@ -74,6 +75,10 @@ const IterationResultPanel: FC<Props> = ({
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
const [retryRunResult, setRetryRunResult] = useState<Record<string, NodeTracing[]> | undefined>()
|
||||||
|
const handleRetryDetail = (v: number, detail?: NodeTracing[]) => {
|
||||||
|
setRetryRunResult({ ...retryRunResult, [v]: detail })
|
||||||
|
}
|
||||||
|
|
||||||
const main = (
|
const main = (
|
||||||
<>
|
<>
|
||||||
@ -116,6 +121,8 @@ const IterationResultPanel: FC<Props> = ({
|
|||||||
{expandedIterations[index] && <div
|
{expandedIterations[index] && <div
|
||||||
className="flex-grow h-px bg-divider-subtle"
|
className="flex-grow h-px bg-divider-subtle"
|
||||||
></div>}
|
></div>}
|
||||||
|
{
|
||||||
|
!retryRunResult?.[index] && (
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
'overflow-hidden transition-all duration-200',
|
'overflow-hidden transition-all duration-200',
|
||||||
expandedIterations[index] ? 'max-h-[1000px] opacity-100' : 'max-h-0 opacity-0',
|
expandedIterations[index] ? 'max-h-[1000px] opacity-100' : 'max-h-0 opacity-0',
|
||||||
@ -123,8 +130,19 @@ const IterationResultPanel: FC<Props> = ({
|
|||||||
<TracingPanel
|
<TracingPanel
|
||||||
list={iteration}
|
list={iteration}
|
||||||
className='bg-background-section-burn'
|
className='bg-background-section-burn'
|
||||||
|
onShowRetryDetail={v => handleRetryDetail(index, v)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
retryRunResult?.[index] && (
|
||||||
|
<RetryResultPanel
|
||||||
|
list={retryRunResult[index]}
|
||||||
|
onBack={() => handleRetryDetail(index, undefined)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -216,6 +216,11 @@ const NodePanel: FC<Props> = ({
|
|||||||
{nodeInfo.error}
|
{nodeInfo.error}
|
||||||
</StatusContainer>
|
</StatusContainer>
|
||||||
)}
|
)}
|
||||||
|
{nodeInfo.status === 'retry' && (
|
||||||
|
<StatusContainer status='failed'>
|
||||||
|
{nodeInfo.error}
|
||||||
|
</StatusContainer>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{nodeInfo.inputs && (
|
{nodeInfo.inputs && (
|
||||||
<div className={cn('mb-1')}>
|
<div className={cn('mb-1')}>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user