Compare commits
25 Commits
65f753208a
...
master
Author | SHA1 | Date | |
---|---|---|---|
0c770b805d | |||
029c268af6 | |||
efeeb51e8b | |||
55be6d989e | |||
4bf786336e | |||
bf27b47427 | |||
dc9ade07b6 | |||
c068799b32 | |||
fe15933479 | |||
87f8651bed | |||
e332cc44c9 | |||
a96cf04261 | |||
4d9cb375ec | |||
d6b415a839 | |||
bb088f1d29 | |||
e84950da59 | |||
8c6112ddf8 | |||
18cd67a9ad | |||
5bd0e4335f | |||
fb0a9d875c | |||
162550fd35 | |||
a2ba1440d4 | |||
5971cd569f | |||
dcd2281f33 | |||
262275a894 |
@ -15,14 +15,12 @@ import "context"
|
|||||||
//
|
//
|
||||||
// Date : 14:22 2022/6/23
|
// Date : 14:22 2022/6/23
|
||||||
type ITask interface {
|
type ITask interface {
|
||||||
// Name 任务名称标识, 全局唯一
|
// GetFlag 任务名称标识, 全局唯一
|
||||||
Name() string
|
GetFlag() string
|
||||||
// Description 任务描述
|
// Description 任务描述
|
||||||
Description() string
|
Description() string
|
||||||
// GetRunID 获取任务ID
|
|
||||||
GetRunID() string
|
|
||||||
// Callback 任务执行成功的回调
|
// Callback 任务执行成功的回调
|
||||||
Callback(result *Result) error
|
Callback(result *Result) error
|
||||||
// Execute 执行任务
|
// Execute 执行任务
|
||||||
Execute(ctx context.Context, cfg *Config) (map[string]interface{}, error)
|
Execute(ctx context.Context, cfg *Config) *Result
|
||||||
}
|
}
|
||||||
|
278
core.go
Normal file
278
core.go
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
// Package task ...
|
||||||
|
//
|
||||||
|
// Description : task ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2023-08-04 11:13
|
||||||
|
package task
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/list"
|
||||||
|
"fmt"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/easymap"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewTimeWheel 实例化时间轮
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 16:50 2023/8/11
|
||||||
|
func NewTimeWheel(slotCount int, interval time.Duration) *TimeWheel {
|
||||||
|
if slotCount <= 0 {
|
||||||
|
// 默认100个槽位
|
||||||
|
slotCount = 100
|
||||||
|
}
|
||||||
|
if interval.Seconds() == 0 {
|
||||||
|
// 默认60s扫描一次
|
||||||
|
interval = time.Second * 60
|
||||||
|
}
|
||||||
|
tw := &TimeWheel{
|
||||||
|
interval: interval,
|
||||||
|
slots: make([]*list.List, slotCount),
|
||||||
|
ticker: time.NewTicker(interval),
|
||||||
|
slotCount: slotCount,
|
||||||
|
addTaskChannel: make(chan *Task, 1000),
|
||||||
|
removeTaskChannel: make(chan *Task, 1000),
|
||||||
|
stopChannel: make(chan bool, 1000),
|
||||||
|
taskRecords: easymap.NewNormal(),
|
||||||
|
job: nil,
|
||||||
|
isRunning: false,
|
||||||
|
}
|
||||||
|
tw.initSlots()
|
||||||
|
return tw
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeWheel 核心时间轮的数据结构
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 11:14 2023/8/4
|
||||||
|
type TimeWheel struct {
|
||||||
|
interval time.Duration // 时间轮精度
|
||||||
|
slots []*list.List // 时间轮盘每个位置存储的任务列表
|
||||||
|
ticker *time.Ticker // 定时器
|
||||||
|
currentPosition int // 时间轮盘当前位置
|
||||||
|
slotCount int // 时间轮盘的齿数,Interval*SlotCount就是时间轮盘转一圈走过的时间
|
||||||
|
addTaskChannel chan *Task
|
||||||
|
removeTaskChannel chan *Task
|
||||||
|
stopChannel chan bool
|
||||||
|
taskRecords easymap.EasyMap // Map结构来存储Task对象,key是Task.key,value是Task在双向链表中的存储对象
|
||||||
|
// 需要执行的任务,如果时间轮盘上的Task执行同一个Job,可以直接实例化到TimeWheel结构体中。
|
||||||
|
// 此处的优先级低于Task中的Job参数
|
||||||
|
job ITask
|
||||||
|
isRunning bool // 是否运行中
|
||||||
|
}
|
||||||
|
|
||||||
|
// initSlots 初始化时间轮盘,每个轮盘上的卡槽用一个双向队列表示,便于插入和删除
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 13:37 2023/8/4
|
||||||
|
func (tw *TimeWheel) initSlots() {
|
||||||
|
for i := 0; i < tw.slotCount; i++ {
|
||||||
|
tw.slots[i] = list.New()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start 启动时间轮盘的内部函数
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 13:38 2023/8/4
|
||||||
|
func (tw *TimeWheel) Start() {
|
||||||
|
tw.isRunning = true
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-tw.ticker.C:
|
||||||
|
// 指定时间间隔之后, 调度一次任务
|
||||||
|
tw.checkAndRunTask()
|
||||||
|
case task := <-tw.addTaskChannel:
|
||||||
|
// 此处利用Task.createTime来定位任务在时间轮盘的位置和执行圈数
|
||||||
|
// 如果直接用任务的周期来定位位置,那么在服务重启的时候,任务周器相同的点会被定位到相同的卡槽,
|
||||||
|
// 会造成任务过度集中
|
||||||
|
tw.AddTask(task, false)
|
||||||
|
case task := <-tw.removeTaskChannel:
|
||||||
|
tw.RemoveTask(task)
|
||||||
|
case <-tw.stopChannel:
|
||||||
|
tw.ticker.Stop()
|
||||||
|
tw.isRunning = false
|
||||||
|
// TODO : 重新初始化时间轮实例
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkAndRunTask 检查该轮盘点位上的Task,看哪个需要执行
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 13:39 2023/8/4
|
||||||
|
func (tw *TimeWheel) checkAndRunTask() {
|
||||||
|
|
||||||
|
// 获取该轮盘位置的双向链表
|
||||||
|
currentList := tw.slots[tw.currentPosition]
|
||||||
|
|
||||||
|
if currentList != nil {
|
||||||
|
for item := currentList.Front(); item != nil; {
|
||||||
|
task := item.Value.(*Task)
|
||||||
|
// 如果圈数>0,表示还没到执行时间,更新圈数
|
||||||
|
if task.Circle > 0 {
|
||||||
|
task.Circle--
|
||||||
|
item = item.Next()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行任务时,Task.job是第一优先级,然后是TimeWheel.job
|
||||||
|
if task.Job != nil {
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); nil != r {
|
||||||
|
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
_ = task.Job.Execute(nil, nil)
|
||||||
|
}()
|
||||||
|
} else if tw.job != nil {
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); nil != r {
|
||||||
|
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
_ = tw.job.Execute(nil, nil)
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
fmt.Println(fmt.Sprintf("The task %v don't have job to run", task.Key))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行完成以后,将该任务从时间轮盘删除
|
||||||
|
next := item.Next()
|
||||||
|
tw.taskRecords.Del(task.Key)
|
||||||
|
currentList.Remove(item)
|
||||||
|
|
||||||
|
item = next
|
||||||
|
|
||||||
|
// 重新添加任务到时间轮盘,用Task.interval来获取下一次执行的轮盘位置
|
||||||
|
// 如果times==0,说明已经完成执行周期,不需要再添加任务回时间轮盘
|
||||||
|
if task.Times != 0 {
|
||||||
|
if task.Times < 0 {
|
||||||
|
tw.AddTask(task, true)
|
||||||
|
} else {
|
||||||
|
task.Times--
|
||||||
|
tw.AddTask(task, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 轮盘前进一步
|
||||||
|
if tw.currentPosition == tw.slotCount-1 {
|
||||||
|
tw.currentPosition = 0
|
||||||
|
} else {
|
||||||
|
tw.currentPosition++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTask 添加任务的内部函数, 生成Task在时间轮盘位置和圈数的方式,true表示利用Task.interval来生成,false表示利用Task.createTime生成
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 13:43 2023/8/4
|
||||||
|
func (tw *TimeWheel) AddTask(task *Task, byInterval bool) {
|
||||||
|
if nil == task {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 生成 run_id
|
||||||
|
task.RunID = wrapper.StringFromRandom(128, "").Md5().Value
|
||||||
|
if nil != task.Job {
|
||||||
|
task.Key = task.Job.GetFlag() + "_" + task.RunID
|
||||||
|
}
|
||||||
|
var pos, circle int
|
||||||
|
if byInterval {
|
||||||
|
pos, circle = tw.getPosAndCircleByInterval(task.Interval)
|
||||||
|
} else {
|
||||||
|
pos, circle = tw.getPosAndCircleByCreatedTime(task.CreatedTime, task.Interval, task.Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
task.Circle = circle
|
||||||
|
task.Position = pos
|
||||||
|
|
||||||
|
element := tw.slots[pos].PushBack(task)
|
||||||
|
tw.taskRecords.Set(task.Key, element)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTask 删除任务的内部函数
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 13:44 2023/8/4
|
||||||
|
func (tw *TimeWheel) RemoveTask(task *Task) {
|
||||||
|
// 从map结构中删除
|
||||||
|
taskInfo, _ := tw.taskRecords.Get(task.Key)
|
||||||
|
tw.taskRecords.Del(task.Key)
|
||||||
|
|
||||||
|
// 通过TimeWheel.slots获取任务的
|
||||||
|
currentList := tw.slots[task.Position]
|
||||||
|
currentList.Remove(taskInfo.(*list.Element))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPosAndCircleByInterval 该函数通过任务的周期来计算下次执行的位置和圈数
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 13:46 2023/8/4
|
||||||
|
func (tw *TimeWheel) getPosAndCircleByInterval(d time.Duration) (int, int) {
|
||||||
|
delaySeconds := int(d.Seconds())
|
||||||
|
intervalSeconds := int(tw.interval.Seconds())
|
||||||
|
circle := delaySeconds / intervalSeconds / tw.slotCount
|
||||||
|
pos := (tw.currentPosition + delaySeconds/intervalSeconds) % tw.slotCount
|
||||||
|
|
||||||
|
// 特殊case,当计算的位置和当前位置重叠时,因为当前位置已经走过了,所以circle需要减一
|
||||||
|
if pos == tw.currentPosition && circle != 0 {
|
||||||
|
circle--
|
||||||
|
}
|
||||||
|
return pos, circle
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPosAndCircleByCreatedTime 该函数用任务的创建时间来计算下次执行的位置和圈数
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 13:47 2023/8/4
|
||||||
|
func (tw *TimeWheel) getPosAndCircleByCreatedTime(createdTime time.Time, d time.Duration, key any) (int, int) {
|
||||||
|
|
||||||
|
passedTime := time.Since(createdTime) // 计算从创建时间到现在经过了多少时间
|
||||||
|
passedSeconds := int(passedTime.Seconds()) // 从开始到现在经历的秒数
|
||||||
|
delaySeconds := int(d.Seconds()) // 多久之后执行
|
||||||
|
intervalSeconds := int(tw.interval.Seconds()) // 时间轮盘的间隔秒数
|
||||||
|
|
||||||
|
circle := delaySeconds / intervalSeconds / tw.slotCount // 计算需要走多少圈
|
||||||
|
pos := (tw.currentPosition + (delaySeconds-(passedSeconds%delaySeconds))/intervalSeconds) % tw.slotCount // 计算下次执行的位置
|
||||||
|
|
||||||
|
// 特殊case,当计算的位置和当前位置重叠时,因为当前位置已经走过了,所以circle需要减一
|
||||||
|
if pos == tw.currentPosition && circle != 0 {
|
||||||
|
circle--
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos, circle
|
||||||
|
}
|
||||||
|
|
||||||
|
// Task 任务数据结构
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 11:44 2023/8/4
|
||||||
|
type Task struct {
|
||||||
|
RunID string // 每一次运行的run id
|
||||||
|
Key string // 用来标识task对象,是唯一的
|
||||||
|
Interval time.Duration // 任务周期
|
||||||
|
CreatedTime time.Time // 任务的创建时间
|
||||||
|
Position int // 任务在轮盘的位置
|
||||||
|
Circle int // 任务需要在轮盘走多少圈才能执行
|
||||||
|
Job ITask // 任务需要执行的Job,优先级高于TimeWheel中的Job
|
||||||
|
Times int // 任务需要执行的次数,如果需要一直执行,设置成-1
|
||||||
|
MaxExecuteTime int64 // 最大执行时长, 超时自动取消. 如不限制时长, 设置成0
|
||||||
|
}
|
66
core_test.go
Normal file
66
core_test.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Package task ...
|
||||||
|
//
|
||||||
|
// Description : task ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2023-08-11 17:00
|
||||||
|
package task
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var tw *TimeWheel
|
||||||
|
|
||||||
|
// TestNewTimeWheel ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 17:00 2023/8/11
|
||||||
|
func TestNewTimeWheel(t *testing.T) {
|
||||||
|
tw = NewTimeWheel(10, time.Second)
|
||||||
|
tw.AddTask(&Task{
|
||||||
|
Key: wrapper.StringFromRandom(32, "").Value(),
|
||||||
|
Interval: 5 * time.Second,
|
||||||
|
CreatedTime: time.Now(),
|
||||||
|
Position: 0,
|
||||||
|
Circle: 100,
|
||||||
|
Job: &testTask{},
|
||||||
|
Times: 10,
|
||||||
|
MaxExecuteTime: 0,
|
||||||
|
}, false)
|
||||||
|
go tw.Start()
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
for tw.isRunning {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type testTask struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t testTask) GetFlag() string {
|
||||||
|
return "unit_test"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t testTask) Description() string {
|
||||||
|
return "单元测试任务"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t testTask) GetRunID() string {
|
||||||
|
return wrapper.StringFromRandom(32, "").Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t testTask) Callback(result *Result) error {
|
||||||
|
fmt.Println(result)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t testTask) Execute(ctx context.Context, cfg *Config) *Result {
|
||||||
|
fmt.Println(wrapper.OwnTimeFromNow().ToString())
|
||||||
|
return nil
|
||||||
|
}
|
29
define.go
29
define.go
@ -13,16 +13,18 @@ package task
|
|||||||
//
|
//
|
||||||
// Date : 14:26 2022/6/23
|
// Date : 14:26 2022/6/23
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// TaskName 执行的任务名称
|
|
||||||
TaskName string
|
|
||||||
// Async 是否异步运行
|
|
||||||
Async bool
|
|
||||||
// Timeout 单位 : 秒, <= 0认为不设置超时
|
// Timeout 单位 : 秒, <= 0认为不设置超时
|
||||||
Timeout int
|
Timeout int
|
||||||
// ForbiddenCallback 禁用执行结果回调
|
// ForbiddenCallback 禁用执行结果回调
|
||||||
ForbiddenCallback bool
|
ForbiddenCallback bool
|
||||||
// Param 任务执行参数
|
// Param 任务执行参数
|
||||||
Param map[string]interface{}
|
Param map[string]any
|
||||||
|
// TaskFlag 任务标识
|
||||||
|
TaskFlag string
|
||||||
|
// TaskName 任务名称
|
||||||
|
TaskName string
|
||||||
|
// Async 是否异步
|
||||||
|
Async bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result 执行结果
|
// Result 执行结果
|
||||||
@ -31,13 +33,12 @@ type Config struct {
|
|||||||
//
|
//
|
||||||
// Date : 14:43 2022/6/23
|
// Date : 14:43 2022/6/23
|
||||||
type Result struct {
|
type Result struct {
|
||||||
StartTime int64 // 开始时间, 纳秒
|
StartTime int64 // 开始时间, 纳秒
|
||||||
FinishTime int64 // 结束时间, 纳秒
|
FinishTime int64 // 结束时间, 纳秒
|
||||||
Used int64 // 耗时, 纳秒
|
Used int64 // 耗时, 纳秒
|
||||||
TaskRunID string // 任务运行ID
|
TaskRunID string // 任务运行ID
|
||||||
TaskDescription string // 任务描述
|
TaskDescription string // 任务描述
|
||||||
TaskConfig *Config // 任务配置
|
TaskConfig *Config // 任务配置
|
||||||
Async bool // 是否运行
|
Data map[string]any // 任务结果数据
|
||||||
Data map[string]interface{} // 任务结果数据
|
Err error // 异常信息, err == nil , 代表执行成功
|
||||||
Err error // 异常信息, err == nil , 代表执行成功
|
|
||||||
}
|
}
|
||||||
|
17
error.go
Normal file
17
error.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Package task ...
|
||||||
|
//
|
||||||
|
// Description : 内置的错误信息
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2023-08-04 11:50
|
||||||
|
package task
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrDuplicateTaskKey 任务key重复
|
||||||
|
ErrDuplicateTaskKey = errors.New("duplicate task key")
|
||||||
|
// ErrTaskKeyNotFound 任务key不存在
|
||||||
|
ErrTaskKeyNotFound = errors.New("task key doesn't existed in task list, please check your input")
|
||||||
|
)
|
27
go.mod
27
go.mod
@ -1,3 +1,28 @@
|
|||||||
module git.zhangdeman.cn/zhangdeman/task
|
module git.zhangdeman.cn/zhangdeman/task
|
||||||
|
|
||||||
go 1.17
|
go 1.23.0
|
||||||
|
|
||||||
|
toolchain go1.24.3
|
||||||
|
|
||||||
|
require (
|
||||||
|
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4
|
||||||
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995 // indirect
|
||||||
|
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
|
||||||
|
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9 // indirect
|
||||||
|
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
|
||||||
|
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||||
|
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
|
||||||
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/mozillazg/go-pinyin v0.20.0 // indirect
|
||||||
|
github.com/sbabiv/xml2map v1.2.1 // indirect
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
|
github.com/tidwall/gjson v1.18.0 // indirect
|
||||||
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
|
53
go.sum
Normal file
53
go.sum
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995 h1:LmPRAf0AsxRVFPibdpZR89ajlsz8hof2IvMMyTqiEq4=
|
||||||
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
|
||||||
|
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 h1:s6d4b6yY+NaK1AzoBD1pxqsuygEHQz0Oie86c45geDw=
|
||||||
|
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4/go.mod h1:V4Dfg1v/JVIZGEKCm6/aehs8hK+Xow1dkL1yiQymXlQ=
|
||||||
|
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 h1:gUDlQMuJ4xNfP2Abl1Msmpa3fASLWYkNlqDFF/6GN0Y=
|
||||||
|
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
|
||||||
|
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9 h1:/GLQaFoLb+ciHOtAS2BIyPNnf4O5ME3AC5PUaJY9kfs=
|
||||||
|
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9/go.mod h1:ABJ655C5QenQNOzf7LjCe4sSB52CXvaWLX2Zg4uwDJY=
|
||||||
|
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI=
|
||||||
|
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
|
||||||
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 h1:zPUoylfJTbc0EcxW+NEzOTBmoeFZ2I/rLFBnEzxb4Wk=
|
||||||
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740/go.mod h1:1ct92dbVc49pmXusA/iGfcQUJzcYmJ+cjAhgc3sDv1I=
|
||||||
|
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||||
|
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
|
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
|
||||||
|
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||||
|
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
|
||||||
|
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ=
|
||||||
|
github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/sbabiv/xml2map v1.2.1 h1:1lT7t0hhUvXZCkdxqtq4n8/ZCnwLWGq4rDuDv5XOoFE=
|
||||||
|
github.com/sbabiv/xml2map v1.2.1/go.mod h1:2TPoAfcaM7+Sd4iriPvzyntb2mx7GY+kkQpB/GQa/eo=
|
||||||
|
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
|
||||||
|
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
|
||||||
|
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
||||||
|
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||||
|
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
18
task.go
18
task.go
@ -10,6 +10,7 @@ package task
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -51,10 +52,10 @@ func (d *dispatch) Register(taskInstanceList ...ITask) error {
|
|||||||
if nil == taskInstance {
|
if nil == taskInstance {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, exist := d.taskTable[taskInstance.Name()]; exist {
|
if _, exist := d.taskTable[taskInstance.GetFlag()]; exist {
|
||||||
return fmt.Errorf("%s 任务重复注册! ", taskInstance.Name())
|
return fmt.Errorf("%s 任务重复注册! ", taskInstance.GetFlag())
|
||||||
}
|
}
|
||||||
d.taskTable[taskInstance.Name()] = taskInstance
|
d.taskTable[taskInstance.GetFlag()] = taskInstance
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -104,12 +105,11 @@ func (d *dispatch) Run(ctx context.Context, cfg *Config) *Result {
|
|||||||
StartTime: time.Now().UnixNano(),
|
StartTime: time.Now().UnixNano(),
|
||||||
FinishTime: 0,
|
FinishTime: 0,
|
||||||
Used: 0,
|
Used: 0,
|
||||||
TaskRunID: "",
|
TaskRunID: wrapper.StringFromRandom(64, "").Md5().Value,
|
||||||
TaskDescription: "",
|
TaskDescription: "",
|
||||||
TaskConfig: cfg,
|
TaskConfig: cfg,
|
||||||
Data: nil,
|
Data: nil,
|
||||||
Err: nil,
|
Err: nil,
|
||||||
Async: cfg.Async,
|
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
result.FinishTime = time.Now().UnixNano()
|
result.FinishTime = time.Now().UnixNano()
|
||||||
@ -120,8 +120,6 @@ func (d *dispatch) Run(ctx context.Context, cfg *Config) *Result {
|
|||||||
result.Err = fmt.Errorf("%v 任务未注册", cfg.TaskName)
|
result.Err = fmt.Errorf("%v 任务未注册", cfg.TaskName)
|
||||||
}
|
}
|
||||||
d.lock.RUnlock()
|
d.lock.RUnlock()
|
||||||
result.TaskRunID = taskInstance.GetRunID()
|
|
||||||
result.TaskDescription = taskInstance.Description()
|
|
||||||
if cfg.Async {
|
if cfg.Async {
|
||||||
// 异步运行
|
// 异步运行
|
||||||
go func() {
|
go func() {
|
||||||
@ -133,11 +131,13 @@ func (d *dispatch) Run(ctx context.Context, cfg *Config) *Result {
|
|||||||
result.Err = fmt.Errorf("出现其他场景Panic : %v", e)
|
result.Err = fmt.Errorf("出现其他场景Panic : %v", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.Data, result.Err = taskInstance.Execute(ctx, cfg)
|
result = taskInstance.Execute(ctx, cfg)
|
||||||
|
result.TaskDescription = taskInstance.Description()
|
||||||
_ = taskInstance.Callback(result)
|
_ = taskInstance.Callback(result)
|
||||||
}()
|
}()
|
||||||
} else {
|
} else {
|
||||||
result.Data, result.Err = taskInstance.Execute(ctx, cfg)
|
result = taskInstance.Execute(ctx, cfg)
|
||||||
|
result.TaskDescription = taskInstance.Description()
|
||||||
_ = taskInstance.Callback(result)
|
_ = taskInstance.Callback(result)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
Reference in New Issue
Block a user