mirror of
https://github.com/certimate-go/certimate.git
synced 2026-06-13 21:01:32 +08:00
feat: optimize workflow engine error handling
This commit is contained in:
parent
6f28b4066e
commit
9d1dc8564f
@ -232,6 +232,10 @@ func (wd *workflowDispatcher) tryExecuteAsync(task *taskInfo) {
|
||||
return nil
|
||||
})
|
||||
we.OnNodeError(func(ctx context.Context, node *engine.Node, err error) error {
|
||||
if errors.Is(err, engine.ErrTerminated) || errors.Is(err, engine.ErrBlocksException) {
|
||||
return nil
|
||||
}
|
||||
|
||||
log := domain.WorkflowLog{}
|
||||
log.WorkflowId = task.WorkflowId
|
||||
log.RunId = task.RunId
|
||||
|
||||
@ -62,7 +62,7 @@ func (we *workflowEngine) Invoke(ctx context.Context, workflowId string, runId s
|
||||
SetInputsManager(newInOutManager()).
|
||||
SetContext(ctx)
|
||||
if err := we.executeBlocks(wfCtx, runGraph.Nodes); err != nil {
|
||||
if !errors.Is(err, errInterrupted) {
|
||||
if !errors.Is(err, ErrTerminated) {
|
||||
we.fireOnErrorHooks(ctx, err)
|
||||
return err
|
||||
}
|
||||
@ -135,7 +135,7 @@ func (we *workflowEngine) executeNode(wfCtx *WorkflowContext, node *Node) error
|
||||
|
||||
execCtx := newNodeExecutionContext(wfCtx, node)
|
||||
execRes, err := executor.Execute(execCtx)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, ErrTerminated) {
|
||||
we.fireOnNodeErrorHooks(wfCtx.ctx, node, err)
|
||||
return err
|
||||
}
|
||||
@ -179,11 +179,15 @@ func (we *workflowEngine) executeNode(wfCtx *WorkflowContext, node *Node) error
|
||||
}
|
||||
}
|
||||
|
||||
if execRes.Interrupted {
|
||||
return errInterrupted
|
||||
if execRes.Terminated {
|
||||
return ErrTerminated
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil && errors.Is(err, ErrTerminated) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -4,4 +4,9 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var errInterrupted = errors.New("workflow engine: interrupted, may be ended")
|
||||
var (
|
||||
// 表示工作流引擎执行被中断,可能已结束
|
||||
ErrTerminated = errors.New("workflow engine: execution was terminated")
|
||||
// 表示工作流引擎在执行子节点时发生异常
|
||||
ErrBlocksException = errors.New("workflow engine: error occurred when executing blocks")
|
||||
)
|
||||
|
||||
@ -69,7 +69,7 @@ func newNodeExecutionContext(wfCtx *WorkflowContext, node *Node) *NodeExecutionC
|
||||
type NodeExecutionResult struct {
|
||||
node *Node
|
||||
|
||||
Interrupted bool // 是否中断执行(通常由 End 节点主动触发)
|
||||
Terminated bool // 是否终止执行(通常由 End 节点主动触发)
|
||||
|
||||
variablesMtx sync.Mutex
|
||||
Variables []VariableState
|
||||
|
||||
@ -33,7 +33,7 @@ func (ne *conditionNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeEx
|
||||
|
||||
err := engine.executeNode(execCtx.Clone(), node)
|
||||
if err != nil {
|
||||
if errors.Is(err, errInterrupted) {
|
||||
if errors.Is(err, ErrTerminated) {
|
||||
return execRes, err
|
||||
}
|
||||
errs = append(errs, err)
|
||||
@ -41,7 +41,7 @@ func (ne *conditionNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeEx
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return execRes, fmt.Errorf("error occurred when executing child nodes: %w", errors.Join(errs...))
|
||||
return execRes, fmt.Errorf("%w: %w", ErrBlocksException, errors.Join(errs...))
|
||||
}
|
||||
|
||||
return execRes, nil
|
||||
@ -92,7 +92,7 @@ func (ne *branchBlockNodeExecutor) Execute(execCtx *NodeExecutionContext) (*Node
|
||||
panic("impossible!")
|
||||
} else {
|
||||
if err := engine.executeBlocks(execCtx.Clone(), execCtx.Node.Blocks); err != nil {
|
||||
return execRes, err
|
||||
return execRes, fmt.Errorf("%w: %w", ErrBlocksException, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,9 +8,11 @@ type endNodeExecutor struct {
|
||||
nodeExecutor
|
||||
}
|
||||
|
||||
func (e *endNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeExecutionResult, error) {
|
||||
func (ne *endNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeExecutionResult, error) {
|
||||
execRes := newNodeExecutionResult(execCtx.Node)
|
||||
execRes.Interrupted = true
|
||||
execRes.Terminated = true
|
||||
|
||||
ne.logger.Info("the is ending")
|
||||
|
||||
return execRes, nil
|
||||
}
|
||||
|
||||
@ -8,9 +8,11 @@ type startNodeExecutor struct {
|
||||
nodeExecutor
|
||||
}
|
||||
|
||||
func (e *startNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeExecutionResult, error) {
|
||||
func (ne *startNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeExecutionResult, error) {
|
||||
execRes := newNodeExecutionResult(execCtx.Node)
|
||||
|
||||
ne.logger.Info("")
|
||||
|
||||
return execRes, nil
|
||||
}
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@ func (ne *tryCatchNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeExe
|
||||
|
||||
err := engine.executeNode(execCtx.Clone(), node)
|
||||
if err != nil {
|
||||
if errors.Is(err, errInterrupted) {
|
||||
if errors.Is(err, ErrTerminated) {
|
||||
return execRes, err
|
||||
}
|
||||
tryErrs = append(tryErrs, err)
|
||||
@ -52,18 +52,17 @@ func (ne *tryCatchNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeExe
|
||||
|
||||
err := engine.executeNode(execCtx.Clone(), node)
|
||||
if err != nil {
|
||||
if errors.Is(err, errInterrupted) {
|
||||
if errors.Is(err, ErrTerminated) {
|
||||
return execRes, err
|
||||
}
|
||||
catchErrs = append(catchErrs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(catchErrs) > 0 {
|
||||
return execRes, fmt.Errorf("error occurred when executing child nodes: %w", errors.Join(append(tryErrs, catchErrs...)...))
|
||||
}
|
||||
|
||||
return execRes, fmt.Errorf("error occurred when executing child nodes: %w", errors.Join(tryErrs...))
|
||||
errs := make([]error, 0)
|
||||
errs = append(errs, tryErrs...)
|
||||
errs = append(errs, catchErrs...)
|
||||
return execRes, fmt.Errorf("%w: %w", ErrBlocksException, errors.Join(errs...))
|
||||
}
|
||||
|
||||
return execRes, nil
|
||||
@ -90,7 +89,7 @@ func (ne *tryBlockNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeExe
|
||||
execRes := newNodeExecutionResult(execCtx.Node)
|
||||
|
||||
if err := engine.executeBlocks(execCtx.Clone(), execCtx.Node.Blocks); err != nil {
|
||||
return execRes, err
|
||||
return execRes, fmt.Errorf("%w: %w", ErrBlocksException, err)
|
||||
}
|
||||
|
||||
return execRes, nil
|
||||
@ -117,7 +116,7 @@ func (ne *catchBlockNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeE
|
||||
}
|
||||
|
||||
if err := engine.executeBlocks(execCtx.Clone(), execCtx.Node.Blocks); err != nil {
|
||||
return execRes, err
|
||||
return execRes, fmt.Errorf("%w: %w", ErrBlocksException, err)
|
||||
}
|
||||
|
||||
return execRes, nil
|
||||
|
||||
@ -73,11 +73,11 @@ const InternalNodeCard = ({
|
||||
|
||||
const isActivated = useMemo(() => nodeRenderData.activated || nodeRenderData.lineActivated, [nodeRenderData.activated, nodeRenderData.lineActivated]);
|
||||
const [isHovering, setIsHovering] = useState(false);
|
||||
const [isInvalid, setIsInvalid] = useState(false);
|
||||
const [isNodeInvalid, setIsNodeInvalid] = useState(false);
|
||||
const isNodeDisabled = useWatchFormValueIn(nodeRender.node, "disabled");
|
||||
|
||||
const formState = useWatchFormState(nodeRender.node);
|
||||
useEffect(() => setIsInvalid(!!formState?.invalid), [formState?.invalid]);
|
||||
useEffect(() => setIsNodeInvalid(!!formState?.invalid), [formState?.invalid]);
|
||||
|
||||
return (
|
||||
<Card
|
||||
@ -110,7 +110,7 @@ const InternalNodeCard = ({
|
||||
right: "-1px",
|
||||
bottom: "-1px",
|
||||
borderWidth: "2px",
|
||||
borderColor: isHovering ? "var(--color-primary)" : isInvalid ? "var(--color-error)" : void 0,
|
||||
borderColor: isHovering ? "var(--color-primary)" : isNodeInvalid ? "var(--color-error)" : void 0,
|
||||
borderStyle: isNodeDisabled ? "dashed" : "solid",
|
||||
}}
|
||||
/>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user