Files
data-engine/scheduler/run_sync_task_log_task.go

133 lines
3.5 KiB
Go
Raw Normal View History

2026-04-08 09:03:20 +08:00
package main
import (
"context"
"fmt"
"time"
2026-05-29 18:39:32 +08:00
dao "dataengine/dao/copydata"
taskDto "dataengine/model/dto/copydata"
syncSvc "dataengine/service/sync"
2026-06-10 15:56:02 +08:00
"gitea.redpowerfuture.com/red-future/common/beans"
2026-04-08 09:03:20 +08:00
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
2026-05-29 18:39:32 +08:00
"github.com/gogf/gf/v2/frame/g"
2026-04-08 09:03:20 +08:00
"github.com/gogf/gf/v2/os/gctx"
"github.com/sirupsen/logrus"
)
2026-05-29 18:39:32 +08:00
// CompensationScheduler 通用补偿调度器
2026-04-08 09:03:20 +08:00
type CompensationScheduler struct {
2026-05-29 18:39:32 +08:00
interval time.Duration
2026-04-08 09:03:20 +08:00
}
2026-05-29 18:39:32 +08:00
// NewCompensationScheduler 创建调度器
2026-04-08 09:03:20 +08:00
func NewCompensationScheduler() *CompensationScheduler {
ctx := gctx.New()
2026-05-29 18:39:32 +08:00
sec := g.Cfg().MustGet(ctx, "sync.compensation_interval_seconds", 300).Int()
if sec < 10 {
sec = 300
2026-04-08 09:03:20 +08:00
}
2026-05-29 18:39:32 +08:00
return &CompensationScheduler{interval: time.Duration(sec) * time.Second}
2026-04-08 14:30:09 +08:00
}
2026-04-08 09:03:20 +08:00
2026-05-29 18:39:32 +08:00
// RunOnce 执行一次补偿
func (s *CompensationScheduler) RunOnce() {
ctx := gctx.New()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
2026-04-08 09:03:20 +08:00
2026-05-29 18:39:32 +08:00
logrus.Info("=== 开始补偿扫描 ===")
2026-04-08 09:03:20 +08:00
2026-05-29 18:39:32 +08:00
// 查询所有 failed 状态的任务,不限类型
tasks, err := dao.SyncTaskLog.QueryFailedTasks(ctx, &taskDto.QueryFailedTasksReq{
Status: []string{"failed"},
Limit: 50,
})
2026-04-08 09:03:20 +08:00
if err != nil {
2026-05-29 18:39:32 +08:00
logrus.Errorf("查询失败任务异常: %v", err)
2026-04-08 14:30:09 +08:00
return
2026-04-08 09:03:20 +08:00
}
2026-05-29 18:39:32 +08:00
if len(tasks) == 0 {
logrus.Info("当前没有需要补偿的任务")
2026-04-08 14:30:09 +08:00
return
2026-04-08 09:03:20 +08:00
}
2026-05-29 18:39:32 +08:00
logrus.Infof("发现 %d 个失败任务", len(tasks))
2026-04-08 09:03:20 +08:00
2026-05-29 18:39:32 +08:00
for _, task := range tasks {
if task.RetryCount >= task.MaxRetry {
logrus.Warnf("任务 %s 已达最大重试次数 %d", task.TaskID, task.MaxRetry)
dao.SyncTaskLog.Update(ctx, &taskDto.UpdateSyncTaskLogReq{
ID: task.Id,
Status: "manual_review",
ErrorMessage: fmt.Sprintf("已达最大重试次数 %d", task.MaxRetry),
})
continue
2026-04-08 09:03:20 +08:00
}
2026-05-29 18:39:32 +08:00
platformCode := task.PlatformCode
interfaceCode := task.InterfaceCode
if platformCode == "" || interfaceCode == "" {
logrus.Warnf("任务 %s 缺少 platform_code 或 interface_code跳过", task.TaskID)
continue
2026-04-08 09:03:20 +08:00
}
2026-04-09 09:48:22 +08:00
2026-05-29 18:39:32 +08:00
logrus.Infof("补偿: %s/%s (第 %d 次)", platformCode, interfaceCode, task.RetryCount+1)
// 更新状态为 retrying
retryCount := task.RetryCount + 1
dao.SyncTaskLog.Update(ctx, &taskDto.UpdateSyncTaskLogReq{
ID: task.Id,
Status: "retrying",
RetryCount: &retryCount,
})
// 执行补偿(增量同步)
_, err := syncSvc.SyncByConfig(ctx, platformCode, interfaceCode, false)
if err != nil {
logrus.Errorf("补偿失败: %v", err)
// 更新状态为 failed设置下次重试时间
backoff := []int{5, 15, 30, 60, 120}
waitMin := 5
if retryCount <= len(backoff) {
waitMin = backoff[retryCount-1]
} else {
waitMin = backoff[len(backoff)-1]
2026-04-09 09:48:22 +08:00
}
2026-05-29 18:39:32 +08:00
nextRetry := time.Now().Add(time.Duration(waitMin) * time.Minute)
dao.SyncTaskLog.Update(ctx, &taskDto.UpdateSyncTaskLogReq{
ID: task.Id,
Status: "failed",
ErrorMessage: err.Error(),
ErrorCode: "COMPENSATION_FAILED",
NextRetryTime: nextRetry,
})
} else {
logrus.Infof("补偿成功: %s/%s", platformCode, interfaceCode)
now := time.Now()
dao.SyncTaskLog.Update(ctx, &taskDto.UpdateSyncTaskLogReq{
ID: task.Id,
Status: "success",
CompletedAt: now,
})
2026-04-09 09:48:22 +08:00
}
}
2026-05-29 18:39:32 +08:00
logrus.Info("=== 补偿扫描完成 ===")
2026-04-09 09:48:22 +08:00
}
2026-05-29 18:39:32 +08:00
// Start 启动
func (s *CompensationScheduler) Start() {
logrus.Infof("补偿调度器启动,间隔: %v", s.interval)
s.RunOnce()
ticker := time.NewTicker(s.interval)
defer ticker.Stop()
for range ticker.C {
s.RunOnce()
2026-04-08 09:03:20 +08:00
}
}
func main() {
2026-05-29 18:39:32 +08:00
NewCompensationScheduler().Start()
2026-04-08 09:03:20 +08:00
}