feat(workflow): exec_workflow 增加重试/心跳三列与可恢复查询 DAO
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
flow "ai-agent/workflow/consts/flow"
|
||||
"ai-agent/workflow/consts/public"
|
||||
sessionDto "ai-agent/workflow/model/dto/session"
|
||||
"ai-agent/workflow/model/entity"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gitea.redpowerfuture.com/red-future/common/beans"
|
||||
"gitea.redpowerfuture.com/red-future/common/db/gfdb"
|
||||
@@ -117,3 +120,55 @@ func (d *execWorkflowDao) ListBySession(ctx context.Context, sessionId string) (
|
||||
err = r.Structs(&res)
|
||||
return
|
||||
}
|
||||
|
||||
// ResetRunning 置为运行中并刷新心跳(execute 复用失败记录 / reExecute / 恢复例程共用;
|
||||
// 用 map 更新避免 OmitEmpty 省略 0 值,同时写 status、last_heartbeat、node_group_id)
|
||||
func (d *execWorkflowDao) ResetRunning(ctx context.Context, id int64, nodeGroupId string) error {
|
||||
_, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameExecWorkflow).
|
||||
Where(entity.ExecWorkflowCol.Id, id).
|
||||
Data(map[string]any{
|
||||
entity.ExecWorkflowCol.Status: gconv.Int8(*flow.FlowExecutionStatusRunning.Code()),
|
||||
entity.ExecWorkflowCol.LastHeartbeat: time.Now().UnixMilli(),
|
||||
entity.ExecWorkflowCol.NodeGroupId: nodeGroupId,
|
||||
}).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// TouchHeartbeat 更新执行心跳(毫秒时间戳),供后台心跳 goroutine 每 30s 调用一次
|
||||
func (d *execWorkflowDao) TouchHeartbeat(ctx context.Context, id int64) error {
|
||||
_, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameExecWorkflow).
|
||||
Where(entity.ExecWorkflowCol.Id, id).
|
||||
Data(map[string]any{entity.ExecWorkflowCol.LastHeartbeat: time.Now().UnixMilli()}).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateRetry 更新重试标记与已重试次数(map 更新,retryable=0 也需写入)
|
||||
func (d *execWorkflowDao) UpdateRetry(ctx context.Context, id int64, retryable int, retryCount int) error {
|
||||
_, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameExecWorkflow).
|
||||
Where(entity.ExecWorkflowCol.Id, id).
|
||||
Data(map[string]any{
|
||||
entity.ExecWorkflowCol.Retryable: retryable,
|
||||
entity.ExecWorkflowCol.RetryCount: retryCount,
|
||||
}).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// ListRecoverable 返回可恢复执行:僵尸运行中(status=1 且心跳陈旧)或可重试失败(status=3 且 retryable=1 且未耗尽)
|
||||
func (d *execWorkflowDao) ListRecoverable(ctx context.Context, now int64, staleBefore int64, maxRetry int) (res []*entity.ExecWorkflow, err error) {
|
||||
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameExecWorkflow).
|
||||
Where(fmt.Sprintf("(%s = ? AND %s < ?) OR (%s = ? AND %s = 1 AND %s < ?)",
|
||||
entity.ExecWorkflowCol.Status, entity.ExecWorkflowCol.LastHeartbeat,
|
||||
entity.ExecWorkflowCol.Status, entity.ExecWorkflowCol.Retryable, entity.ExecWorkflowCol.RetryCount),
|
||||
gconv.Int8(*flow.FlowExecutionStatusRunning.Code()), staleBefore,
|
||||
gconv.Int8(*flow.FlowExecutionStatusFailed.Code()), maxRetry).
|
||||
All()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 用 All+Structs 而非 Scan:Scan 生成的列清单会丢嵌入 SQLBaseDO 的 id 等基础列,恢复例程需要 id
|
||||
err = r.Structs(&res)
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user