feat(workflow): 恢复例程 + 心跳 + 启动/周期扫描

This commit is contained in:
2026-08-25 16:44:29 +08:00
parent 788c835580
commit 95dc0d6052
4 changed files with 256 additions and 3 deletions
+18 -1
View File
@@ -156,9 +156,26 @@ func (d *execWorkflowDao) UpdateRetry(ctx context.Context, id int64, retryable i
return err
}
// ListRecoverable 返回可恢复执行:僵尸运行中(status=1 且心跳陈旧)或可重试失败(status=3 且 retryable=1 且未耗尽)
// GetByIdNoTenant 跨租户按 id 读取执行记录(不追加 tenant_id 过滤)。
// 供恢复例程抢锁后、尚未知晓租户时重读 exec 使用;用户路径请继续用租户隔离的 GetById。
func (d *execWorkflowDao) GetByIdNoTenant(ctx context.Context, id int64) (res *entity.ExecWorkflow, err error) {
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameExecWorkflow).
NoTenantId(ctx).
Where(entity.ExecWorkflowCol.Id, id).
One()
if err != nil {
return
}
err = r.Struct(&res)
return
}
// ListRecoverable 返回可恢复执行:僵尸运行中(status=1 且心跳陈旧)或可重试失败(status=3 且 retryable=1 且未耗尽)。
// 调用方是跨租户的恢复扫描(无 HTTP 用户),显式 NoTenantId 走系统级扫描,避免僵尸执行因租户过滤漏检。
// ctx 必须携带 OTel spanNoTenantId 依赖 traceID 作为 gcache 标记键),恢复扫描由 scanAndRecover 保证。
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).
NoTenantId(ctx).
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),