github.com/iikira/iikira-go-utils@v0.0.0-20230610031953-f2cb11cde33a/utils/taskframework/executor.go (about) 1 package taskframework 2 3 import ( 4 "github.com/GeertJohan/go.incremental" 5 "github.com/iikira/iikira-go-utils/utils/waitgroup" 6 "github.com/oleiade/lane" 7 "strconv" 8 "time" 9 ) 10 11 type ( 12 TaskExecutor struct { 13 incr *incremental.Int // 任务id生成 14 deque *lane.Deque // 队列 15 parallel int // 任务的最大并发量 16 17 // 是否统计失败队列 18 IsFailedDeque bool 19 failedDeque *lane.Deque 20 } 21 ) 22 23 func NewTaskExecutor() *TaskExecutor { 24 return &TaskExecutor{} 25 } 26 27 func (te *TaskExecutor) lazyInit() { 28 if te.deque == nil { 29 te.deque = lane.NewDeque() 30 } 31 if te.incr == nil { 32 te.incr = &incremental.Int{} 33 } 34 if te.parallel < 1 { 35 te.parallel = 1 36 } 37 if te.IsFailedDeque { 38 te.failedDeque = lane.NewDeque() 39 } 40 } 41 42 // 设置任务的最大并发量 43 func (te *TaskExecutor) SetParallel(parallel int) { 44 te.parallel = parallel 45 } 46 47 //Append 将任务加到任务队列末尾 48 func (te *TaskExecutor) Append(unit TaskUnit, maxRetry int) *TaskInfo { 49 te.lazyInit() 50 taskInfo := &TaskInfo{ 51 id: strconv.Itoa(te.incr.Next()), 52 maxRetry: maxRetry, 53 } 54 unit.SetTaskInfo(taskInfo) 55 te.deque.Append(&TaskInfoItem{ 56 Info: taskInfo, 57 Unit: unit, 58 }) 59 return taskInfo 60 } 61 62 //AppendNoRetry 将任务加到任务队列末尾, 不重试 63 func (te *TaskExecutor) AppendNoRetry(unit TaskUnit) { 64 te.Append(unit, 0) 65 } 66 67 //Count 返回任务数量 68 func (te *TaskExecutor) Count() int { 69 if te.deque == nil { 70 return 0 71 } 72 return te.deque.Size() 73 } 74 75 //Execute 执行任务 76 func (te *TaskExecutor) Execute() { 77 te.lazyInit() 78 79 for { 80 wg := waitgroup.NewWaitGroup(te.parallel) 81 for { 82 e := te.deque.Shift() 83 if e == nil { // 任务为空 84 break 85 } 86 87 // 获取任务 88 task := e.(*TaskInfoItem) 89 wg.AddDelta() 90 91 go func(task *TaskInfoItem) { 92 defer wg.Done() 93 94 result := task.Unit.Run() 95 96 // 返回结果为空 97 if result == nil { 98 task.Unit.OnComplete(result) 99 return 100 } 101 102 if result.Succeed { 103 task.Unit.OnSuccess(result) 104 task.Unit.OnComplete(result) 105 return 106 } 107 108 // 需要进行重试 109 if result.NeedRetry { 110 // 重试次数超出限制 111 // 执行失败 112 if task.Info.IsExceedRetry() { 113 task.Unit.OnFailed(result) 114 if te.IsFailedDeque { 115 // 加入失败队列 116 te.failedDeque.Append(task) 117 } 118 task.Unit.OnComplete(result) 119 return 120 } 121 122 task.Info.retry++ // 增加重试次数 123 task.Unit.OnRetry(result) // 调用重试 124 task.Unit.OnComplete(result) 125 126 time.Sleep(task.Unit.RetryWait()) // 等待 127 te.deque.Append(task) // 重新加入队列末尾 128 return 129 } 130 131 // 执行失败 132 task.Unit.OnFailed(result) 133 if te.IsFailedDeque { 134 // 加入失败队列 135 te.failedDeque.Append(task) 136 } 137 task.Unit.OnComplete(result) 138 }(task) 139 } 140 141 wg.Wait() 142 143 // 没有任务了 144 if te.deque.Size() == 0 { 145 break 146 } 147 } 148 } 149 150 //FailedDeque 获取失败队列 151 func (te *TaskExecutor) FailedDeque() *lane.Deque { 152 return te.failedDeque 153 } 154 155 //Stop 停止执行 156 func (te *TaskExecutor) Stop() { 157 158 } 159 160 //Pause 暂停执行 161 func (te *TaskExecutor) Pause() { 162 163 } 164 165 //Resume 恢复执行 166 func (te *TaskExecutor) Resume() { 167 }