补偿机制任务协程处理

This commit is contained in:
2026-04-09 15:16:43 +08:00
parent eb5e0af308
commit ee713c5c0f

View File

@@ -7,12 +7,15 @@ import (
"context" "context"
"fmt" "fmt"
"strings" "strings"
"sync"
"sync/atomic"
"time" "time"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2" _ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
"github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gctx"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sync/semaphore"
) )
// CompensationScheduler 补偿调度器,负责扫描和补偿失败的分页同步任务 // CompensationScheduler 补偿调度器,负责扫描和补偿失败的分页同步任务
@@ -58,49 +61,71 @@ func (s *CompensationScheduler) processCompensation(ctx context.Context) {
return return
} }
logrus.Infof("发现 %d 个需要补偿的失败分页任务,开始逐个处理...", len(failedPageTasks)) logrus.Infof("发现 %d 个需要补偿的失败分页任务,开始并发处理...", len(failedPageTasks))
successCount := 0 maxConcurrency := 5
failCount := 0 var successCount int64
var failCount int64
var manualReviewCount int64
sem := semaphore.NewWeighted(int64(maxConcurrency))
var wg sync.WaitGroup
for _, pageTask := range failedPageTasks { for _, pageTask := range failedPageTasks {
if pageTask.RetryCount >= pageTask.MaxRetry { wg.Add(1)
logrus.Warnf("⚠ 分页任务 %s 已达到最大重试次数 %d标记为需人工处理", pageTask.TaskID, pageTask.MaxRetry)
go func(task *taskDto.SyncTaskLogItem) {
defer wg.Done()
if err := sem.Acquire(ctx, 1); err != nil {
logrus.Errorf("获取信号量失败:%v", err)
atomic.AddInt64(&failCount, 1)
return
}
defer sem.Release(1)
if task.RetryCount >= task.MaxRetry {
logrus.Warnf("⚠ 分页任务 %s 已达到最大重试次数 %d标记为需人工处理", task.TaskID, task.MaxRetry)
updateReq := &taskDto.UpdateSyncTaskLogReq{ updateReq := &taskDto.UpdateSyncTaskLogReq{
ID: pageTask.Id, ID: task.Id,
Status: "manual_review", Status: "manual_review",
ErrorMessage: fmt.Sprintf("已达到最大重试次数 %d 次", pageTask.MaxRetry), ErrorMessage: fmt.Sprintf("已达到最大重试次数 %d 次", task.MaxRetry),
ErrorCode: "MAX_RETRY_EXCEEDED", ErrorCode: "MAX_RETRY_EXCEEDED",
} }
dao.SyncTaskLog.Update(ctx, updateReq) dao.SyncTaskLog.Update(ctx, updateReq)
s.sendAlert(pageTask) s.sendAlert(task)
failCount++ atomic.AddInt64(&manualReviewCount, 1)
continue return
} }
logrus.Infof("▶ 开始补偿分页任务:%s (广告主=%d, 第 %d/%d 次重试)", logrus.Infof("▶ 开始补偿分页任务:%s (广告主=%d, 第 %d/%d 次重试)",
pageTask.TaskID, pageTask.AdvertiserID, pageTask.RetryCount+1, pageTask.MaxRetry) task.TaskID, task.AdvertiserID, task.RetryCount+1, task.MaxRetry)
if s.compensatePageTask(ctx, pageTask) { if s.compensatePageTask(ctx, task) {
successCount++ atomic.AddInt64(&successCount, 1)
logrus.Infof("✓ 分页任务 %s 补偿成功", pageTask.TaskID) logrus.Infof("✓ 分页任务 %s 补偿成功", task.TaskID)
parentTaskID := s.extractParentTaskID(pageTask.TaskID) parentTaskID := s.extractParentTaskID(task.TaskID)
if parentTaskID != "" { if parentTaskID != "" {
s.checkAndUpdateParentTaskStatus(ctx, parentTaskID) s.checkAndUpdateParentTaskStatus(ctx, parentTaskID)
} }
} else { } else {
failCount++ atomic.AddInt64(&failCount, 1)
logrus.Warnf("✗ 分页任务 %s 补偿失败", pageTask.TaskID) logrus.Warnf("✗ 分页任务 %s 补偿失败", task.TaskID)
}
}(pageTask)
} }
time.Sleep(1 * time.Second) wg.Wait()
}
logrus.Infof("=== 补偿任务执行完成:总计=%d, 成功=%d, 失败=%d ===", finalSuccess := atomic.LoadInt64(&successCount)
len(failedPageTasks), successCount, failCount) finalFail := atomic.LoadInt64(&failCount)
finalManualReview := atomic.LoadInt64(&manualReviewCount)
logrus.Infof("=== 补偿任务执行完成:总计=%d, 成功=%d, 失败=%d, 需人工处理=%d ===",
len(failedPageTasks), finalSuccess, finalFail, finalManualReview)
} }
// compensatePageTask 补偿单个分页任务重新请求API并插入数据 // compensatePageTask 补偿单个分页任务重新请求API并插入数据
@@ -262,7 +287,6 @@ func (s *CompensationScheduler) extractPageNumber(taskID string) int {
// extractPageSize 从任务日志的 PageInfo 或 RequestParams 字段中提取每页大小 // extractPageSize 从任务日志的 PageInfo 或 RequestParams 字段中提取每页大小
// 优先级PageInfo.page_size > RequestParams.page_size > 默认值10 // 优先级PageInfo.page_size > RequestParams.page_size > 默认值10
func (s *CompensationScheduler) extractPageSize(pageTask *taskDto.SyncTaskLogItem) int { func (s *CompensationScheduler) extractPageSize(pageTask *taskDto.SyncTaskLogItem) int {
// 在 extractPageSize 方法开头添加
logrus.Infof("DEBUG - PageInfo 类型: %T, 值: %+v", pageTask.PageInfo, pageTask.PageInfo) logrus.Infof("DEBUG - PageInfo 类型: %T, 值: %+v", pageTask.PageInfo, pageTask.PageInfo)
logrus.Infof("DEBUG - RequestParams 类型: %T, 值: %+v", pageTask.RequestParams, pageTask.RequestParams) logrus.Infof("DEBUG - RequestParams 类型: %T, 值: %+v", pageTask.RequestParams, pageTask.RequestParams)