fix: 修复工作流断点续跑时执行记录复用逻辑

This commit is contained in:
2026-08-24 08:59:29 +08:00
parent f34566d9ad
commit 75fb40274d
3 changed files with 35 additions and 15 deletions
+15
View File
@@ -315,6 +315,7 @@ func flowContentEqual(a, b *entity.FlowInfo) bool {
func execute(ctx context.Context, conn *wsCommon.WsConnection, execId int64, status flow.FlowExecutionStatus, req *sessionDto.WebSocketExecWorkflowReq) (id int64, err error) {
var nodeGroupId = uuid.NewString()
if g.IsEmpty(execId) {
glog.Infof(ctx, "工作流全新执行execute,无历史记录")
execId, err = sessionDao.ExecWorkflowDao.Insert(ctx, &sessionDto.CreateWorkflowReq{
SessionId: conn.SessionId,
FlowId: req.FlowId,
@@ -330,6 +331,7 @@ func execute(ctx context.Context, conn *wsCommon.WsConnection, execId int64, sta
// FlowExecutionStatus 是 *int8 别名,Code() 返回包级指针,直接 == 是地址比较恒为 false,
// 需解引用按值比较,否则复用失败记录时不会重置为 Running、也不更新 RequestParams
if status != nil && *status == *flow.FlowExecutionStatusFailed.Code() {
glog.Infof(ctx, "工作流断点续跑executeexecId: %v", execId)
_, err = sessionDao.ExecWorkflowDao.Update(ctx, &sessionDto.UpdateWorkflowReq{
Id: execId,
NodeGroupId: nodeGroupId,
@@ -339,6 +341,19 @@ func execute(ctx context.Context, conn *wsCommon.WsConnection, execId int64, sta
if err != nil {
return
}
} else {
glog.Infof(ctx, "工作流全新执行executelastExec: %v", execId)
execId, err = sessionDao.ExecWorkflowDao.Insert(ctx, &sessionDto.CreateWorkflowReq{
SessionId: conn.SessionId,
FlowId: req.FlowId,
NodeGroupId: nodeGroupId,
Status: flow.FlowExecutionStatusRunning.Code(),
RequestParams: req.FlowContent,
})
if err != nil || g.IsEmpty(execId) {
glog.Errorf(ctx, "工作流执行记录创建失败: %v", err)
return
}
}
}
+3 -1
View File
@@ -137,7 +137,9 @@ func ModelLambda(ctx context.Context, input any) (any, error) {
// 4.5 视频模型节点返回多个视频时,自动调用视频合成工具(concat_videos)合并为单条;
// 已显式配置 concat_videos 后置工具时跳过,避免重复合并
if nodeInput.Config.PostTool != media.ProcessorName && len(outputRes) > 1 && isVideoModel(ctx, nodeInput.Config.ModelConfig.ModelId) {
g.Log().Debugf(ctx, "modelId1:%v ,outputRes: %v", nodeInput.Config.ModelConfig.ModelId, outputRes)
outputRes, err = invokePostTool(ctx, media.ProcessorName, outputRes, map[string]any{"callback_url": "callback_url", "upload": true})
g.Log().Debugf(ctx, "modelId2:%v ,outputRes: %v", nodeInput.Config.ModelConfig.ModelId, outputRes)
if err != nil {
return nil, err
}
@@ -148,7 +150,7 @@ func ModelLambda(ctx context.Context, input any) (any, error) {
return nil, err
}
}
g.Log().Debugf(ctx, "modelId:%v ,outputRes: %v", nodeInput.Config.ModelConfig.ModelId, outputRes)
g.Log().Debugf(ctx, "modelId3:%v ,outputRes: %v", nodeInput.Config.ModelConfig.ModelId, outputRes)
nodeInput.Config.OutputResult = outputRes
return nodeInput, nil
}
+17 -14
View File
@@ -186,21 +186,24 @@ func resolveValueSource(global *flowDto.FlowExecutionInput, nodeId, field string
}
}
default:
// templates 是模型节点在前端配置的静态输出模板,不在 OutputResult 中,需单独取
if field == "templates" {
value = nodeConfig.Templates
} else {
for _, output := range nodeConfig.OutputResult {
// 模型节点输出记录是单 key 的字面量扁平 key(如 "choices.attrs[0].attrs.delta.attrs.content"),
// gjson 会把 . 和 [0] 当结构路径解析,无法命中字面量 key,故先按字面量 key 直接取值;
// 未命中再回退 gjson 路径查询(兼容真正嵌套的输出结构)。
if v, has := output[field]; has {
value = v
} else {
value = gjson.Get(gconv.String(output), field).Value()
}
if !g.IsEmpty(value) {
return value, gjson.Get(gconv.String(output), CleanFieldPath("refsName")).Value(), true
}
if !g.IsEmpty(nodeConfig.Templates) {
return nodeConfig.Templates, "", true
}
return nil, nil, false
}
for _, output := range nodeConfig.OutputResult {
// 模型节点输出记录是单 key 的字面量扁平 key(如 "choices.attrs[0].attrs.delta.attrs.content"),
// gjson 会把 . 和 [0] 当结构路径解析,无法命中字面量 key,故先按字面量 key 直接取值;
// 未命中再回退 gjson 路径查询(兼容真正嵌套的输出结构)。
if v, has := output[field]; has {
value = v
} else {
value = gjson.Get(gconv.String(output), field).Value()
}
if !g.IsEmpty(value) {
return value, gjson.Get(gconv.String(output), CleanFieldPath("refsName")).Value(), true
}
}
}