mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 17:18:40 +08:00
feat(workflow): enhance trigger node handling with event listening and state management
This commit is contained in:
parent
4ae23ed0f9
commit
9aa43c9165
@ -10,7 +10,14 @@ import {
|
|||||||
import { getNodeInfoById, isConversationVar, isENV, isSystemVar, toNodeOutputVars } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
import { getNodeInfoById, isConversationVar, isENV, isSystemVar, toNodeOutputVars } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||||
|
|
||||||
import type { CommonNodeType, InputVar, ValueSelector, Var, Variable } from '@/app/components/workflow/types'
|
import type { CommonNodeType, InputVar, ValueSelector, Var, Variable } from '@/app/components/workflow/types'
|
||||||
import { BlockEnum, InputVarType, NodeRunningStatus, VarType } from '@/app/components/workflow/types'
|
import {
|
||||||
|
BlockEnum,
|
||||||
|
InputVarType,
|
||||||
|
NodeRunningStatus,
|
||||||
|
VarType,
|
||||||
|
} from '@/app/components/workflow/types'
|
||||||
|
import type { TriggerNodeType } from '@/app/components/workflow/types'
|
||||||
|
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
|
||||||
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
|
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
|
||||||
import { fetchNodeInspectVars, getIterationSingleNodeRunUrl, getLoopSingleNodeRunUrl, singleNodeRun } from '@/service/workflow'
|
import { fetchNodeInspectVars, getIterationSingleNodeRunUrl, getLoopSingleNodeRunUrl, singleNodeRun } from '@/service/workflow'
|
||||||
import Toast from '@/app/components/base/toast'
|
import Toast from '@/app/components/base/toast'
|
||||||
@ -50,9 +57,10 @@ import {
|
|||||||
useStoreApi,
|
useStoreApi,
|
||||||
} from 'reactflow'
|
} from 'reactflow'
|
||||||
import { useInvalidLastRun } from '@/service/use-workflow'
|
import { useInvalidLastRun } from '@/service/use-workflow'
|
||||||
import useInspectVarsCrud from '../../../hooks/use-inspect-vars-crud'
|
import useInspectVarsCrud from '@/app/components/workflow/hooks/use-inspect-vars-crud'
|
||||||
import type { FlowType } from '@/types/common'
|
import type { FlowType } from '@/types/common'
|
||||||
import useMatchSchemaType from '../components/variable/use-match-schema-type'
|
import useMatchSchemaType from '../components/variable/use-match-schema-type'
|
||||||
|
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||||
// eslint-disable-next-line ts/no-unsafe-function-type
|
// eslint-disable-next-line ts/no-unsafe-function-type
|
||||||
const checkValidFns: Record<BlockEnum, Function> = {
|
const checkValidFns: Record<BlockEnum, Function> = {
|
||||||
[BlockEnum.LLM]: checkLLMValid,
|
[BlockEnum.LLM]: checkLLMValid,
|
||||||
@ -189,6 +197,12 @@ const useOneStepRun = <T>({
|
|||||||
const store = useStoreApi()
|
const store = useStoreApi()
|
||||||
const {
|
const {
|
||||||
setShowSingleRunPanel,
|
setShowSingleRunPanel,
|
||||||
|
setIsListening,
|
||||||
|
setListeningTriggerType,
|
||||||
|
setListeningTriggerNodeId,
|
||||||
|
setListeningTriggerNodeIds,
|
||||||
|
setListeningTriggerIsAll,
|
||||||
|
setShowVariableInspectPanel,
|
||||||
} = workflowStore.getState()
|
} = workflowStore.getState()
|
||||||
const invalidLastRun = useInvalidLastRun(flowType, flowId!, id)
|
const invalidLastRun = useInvalidLastRun(flowType, flowId!, id)
|
||||||
const [runResult, doSetRunResult] = useState<NodeRunResult | null>(null)
|
const [runResult, doSetRunResult] = useState<NodeRunResult | null>(null)
|
||||||
@ -212,6 +226,7 @@ const useOneStepRun = <T>({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
isPausedRef.current = isPaused
|
isPausedRef.current = isPaused
|
||||||
}, [isPaused])
|
}, [isPaused])
|
||||||
|
const { eventEmitter } = useEventEmitterContextContext()
|
||||||
|
|
||||||
const setRunResult = useCallback(async (data: NodeRunResult | null) => {
|
const setRunResult = useCallback(async (data: NodeRunResult | null) => {
|
||||||
const isPaused = isPausedRef.current
|
const isPaused = isPausedRef.current
|
||||||
@ -282,6 +297,50 @@ const useOneStepRun = <T>({
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const isWebhookTriggerNode = data.type === BlockEnum.TriggerWebhook
|
||||||
|
const isPluginTriggerNode = data.type === BlockEnum.TriggerPlugin
|
||||||
|
const isTriggerNode = isWebhookTriggerNode || isPluginTriggerNode
|
||||||
|
|
||||||
|
const startTriggerListening = useCallback(() => {
|
||||||
|
if (!isTriggerNode)
|
||||||
|
return
|
||||||
|
|
||||||
|
setIsListening(true)
|
||||||
|
setShowVariableInspectPanel(true)
|
||||||
|
setListeningTriggerType(data.type as TriggerNodeType)
|
||||||
|
setListeningTriggerNodeId(id)
|
||||||
|
setListeningTriggerNodeIds([id])
|
||||||
|
setListeningTriggerIsAll(false)
|
||||||
|
}, [
|
||||||
|
isTriggerNode,
|
||||||
|
setIsListening,
|
||||||
|
setShowVariableInspectPanel,
|
||||||
|
setListeningTriggerType,
|
||||||
|
data.type,
|
||||||
|
setListeningTriggerNodeId,
|
||||||
|
id,
|
||||||
|
setListeningTriggerNodeIds,
|
||||||
|
setListeningTriggerIsAll,
|
||||||
|
])
|
||||||
|
|
||||||
|
const stopTriggerListening = useCallback(() => {
|
||||||
|
if (!isTriggerNode)
|
||||||
|
return
|
||||||
|
|
||||||
|
setIsListening(false)
|
||||||
|
setListeningTriggerType(null)
|
||||||
|
setListeningTriggerNodeId(null)
|
||||||
|
setListeningTriggerNodeIds([])
|
||||||
|
setListeningTriggerIsAll(false)
|
||||||
|
}, [
|
||||||
|
isTriggerNode,
|
||||||
|
setIsListening,
|
||||||
|
setListeningTriggerType,
|
||||||
|
setListeningTriggerNodeId,
|
||||||
|
setListeningTriggerNodeIds,
|
||||||
|
setListeningTriggerIsAll,
|
||||||
|
])
|
||||||
|
|
||||||
const runWebhookSingleRun = useCallback(async (): Promise<any | null> => {
|
const runWebhookSingleRun = useCallback(async (): Promise<any | null> => {
|
||||||
const urlPath = `/apps/${flowId}/workflows/draft/nodes/${id}/trigger/run`
|
const urlPath = `/apps/${flowId}/workflows/draft/nodes/${id}/trigger/run`
|
||||||
|
|
||||||
@ -517,15 +576,16 @@ const useOneStepRun = <T>({
|
|||||||
const isCompleted = runningStatus === NodeRunningStatus.Succeeded || runningStatus === NodeRunningStatus.Failed
|
const isCompleted = runningStatus === NodeRunningStatus.Succeeded || runningStatus === NodeRunningStatus.Failed
|
||||||
|
|
||||||
const handleRun = async (submitData: Record<string, any>) => {
|
const handleRun = async (submitData: Record<string, any>) => {
|
||||||
const isWebhookNode = data.type === BlockEnum.TriggerWebhook
|
if (isWebhookTriggerNode)
|
||||||
const isPluginNode = data.type === BlockEnum.TriggerPlugin
|
|
||||||
const isTriggerNode = isWebhookNode || isPluginNode
|
|
||||||
|
|
||||||
if (isWebhookNode)
|
|
||||||
cancelWebhookSingleRun()
|
cancelWebhookSingleRun()
|
||||||
if (isPluginNode)
|
if (isPluginTriggerNode)
|
||||||
cancelPluginSingleRun()
|
cancelPluginSingleRun()
|
||||||
|
|
||||||
|
if (isTriggerNode)
|
||||||
|
startTriggerListening()
|
||||||
|
else
|
||||||
|
stopTriggerListening()
|
||||||
|
|
||||||
handleNodeDataUpdate({
|
handleNodeDataUpdate({
|
||||||
id,
|
id,
|
||||||
data: {
|
data: {
|
||||||
@ -538,7 +598,7 @@ const useOneStepRun = <T>({
|
|||||||
let hasError = false
|
let hasError = false
|
||||||
try {
|
try {
|
||||||
if (!isIteration && !isLoop) {
|
if (!isIteration && !isLoop) {
|
||||||
if (isWebhookNode) {
|
if (isWebhookTriggerNode) {
|
||||||
res = await runWebhookSingleRun()
|
res = await runWebhookSingleRun()
|
||||||
if (!res) {
|
if (!res) {
|
||||||
if (webhookSingleRunActiveRef.current) {
|
if (webhookSingleRunActiveRef.current) {
|
||||||
@ -554,7 +614,7 @@ const useOneStepRun = <T>({
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isPluginNode) {
|
else if (isPluginTriggerNode) {
|
||||||
res = await runPluginSingleRun()
|
res = await runPluginSingleRun()
|
||||||
if (!res) {
|
if (!res) {
|
||||||
if (pluginSingleRunActiveRef.current) {
|
if (pluginSingleRunActiveRef.current) {
|
||||||
@ -817,10 +877,12 @@ const useOneStepRun = <T>({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (isWebhookNode)
|
if (isWebhookTriggerNode)
|
||||||
cancelWebhookSingleRun()
|
cancelWebhookSingleRun()
|
||||||
if (isPluginNode)
|
if (isPluginTriggerNode)
|
||||||
cancelPluginSingleRun()
|
cancelPluginSingleRun()
|
||||||
|
if (isTriggerNode)
|
||||||
|
stopTriggerListening()
|
||||||
if (!isPausedRef.current && !isIteration && !isLoop && res) {
|
if (!isPausedRef.current && !isIteration && !isLoop && res) {
|
||||||
setRunResult({
|
setRunResult({
|
||||||
...res,
|
...res,
|
||||||
@ -846,18 +908,37 @@ const useOneStepRun = <T>({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleStop = () => {
|
const handleStop = useCallback(() => {
|
||||||
|
if (isTriggerNode) {
|
||||||
|
const isTriggerActive = runningStatus === NodeRunningStatus.Listening
|
||||||
|
|| webhookSingleRunActiveRef.current
|
||||||
|
|| pluginSingleRunActiveRef.current
|
||||||
|
if (!isTriggerActive)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else if (runningStatus !== NodeRunningStatus.Running) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
cancelWebhookSingleRun()
|
cancelWebhookSingleRun()
|
||||||
cancelPluginSingleRun()
|
cancelPluginSingleRun()
|
||||||
handleNodeDataUpdate({
|
handleNodeDataUpdate({
|
||||||
id,
|
id,
|
||||||
data: {
|
data: {
|
||||||
...data,
|
|
||||||
_isSingleRun: false,
|
_isSingleRun: false,
|
||||||
_singleRunningStatus: NodeRunningStatus.Stopped,
|
_singleRunningStatus: NodeRunningStatus.Stopped,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
stopTriggerListening()
|
||||||
|
}, [
|
||||||
|
isTriggerNode,
|
||||||
|
runningStatus,
|
||||||
|
cancelWebhookSingleRun,
|
||||||
|
cancelPluginSingleRun,
|
||||||
|
handleNodeDataUpdate,
|
||||||
|
id,
|
||||||
|
stopTriggerListening,
|
||||||
|
])
|
||||||
|
|
||||||
const toVarInputs = (variables: Variable[]): InputVar[] => {
|
const toVarInputs = (variables: Variable[]): InputVar[] => {
|
||||||
if (!variables)
|
if (!variables)
|
||||||
@ -920,6 +1001,11 @@ const useOneStepRun = <T>({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eventEmitter?.useSubscription((v: any) => {
|
||||||
|
if (v.type === EVENT_WORKFLOW_STOP)
|
||||||
|
handleStop()
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isShowSingleRun,
|
isShowSingleRun,
|
||||||
hideSingleRun,
|
hideSingleRun,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user