├── .gitignore ├── task_test.go ├── README.md └── task.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /task_test.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | func TestRunTask(t *testing.T) { 11 | 12 | // init 13 | InitTaskReceiver(runtime.NumCPU()) 14 | 15 | // add task 16 | AddTask(NewTask( 17 | map[string]interface{}{ 18 | "paramA": "value", 19 | }, // parameter 20 | []FacFunc{func(uuid string, param map[string]interface{}) (string, error) { 21 | fmt.Println(uuid) 22 | fmt.Println(param) 23 | return "ok", nil 24 | }}, -1), 25 | ) 26 | 27 | time.Sleep(time.Second * 5) 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-task 2 | 3 | simple asynchronous task generator tool writed by go 4 | 5 | ## install 6 | 7 | ``` 8 | go get github.com/chenhg5/go-task 9 | ``` 10 | 11 | ## usage 12 | 13 | ``` 14 | import ( 15 | "runtime" 16 | "fmt" 17 | "time" 18 | "github.com/chenhg5/go-task" 19 | ) 20 | 21 | func main() { 22 | 23 | // init 24 | task.InitTaskReceiver(runtime.NumCPU()) 25 | 26 | // add task: parameter, taskList, expiration 27 | task.AddTask(task.NewTask( 28 | map[string]interface{}{ 29 | "paramA" : "value", 30 | }, // parameter 31 | []task.FacFunc{func(uuid string, param map[string]interface{}) (string, error) { 32 | fmt.Println(uuid) 33 | fmt.Println(param) 34 | return "ok", nil 35 | }}, -1), 36 | ) 37 | 38 | time.Sleep(time.Second * 5) 39 | } 40 | ``` 41 | 42 | ## todo 43 | 44 | - [ ] get the number of statistical state 45 | - [ ] api for putting an end to a task 46 | - [ ] api for clearing task list 47 | - [ ] add task delay list -------------------------------------------------------------------------------- /task.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "math/rand" 5 | "runtime" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | const ( 11 | StateWaiting = "waiting" 12 | StateCompleted = "completed" 13 | StateError = "failed" 14 | StateNone = "none" 15 | StateOverdue = "overdue" 16 | ) 17 | 18 | var ( 19 | taskStateMutex sync.Mutex 20 | taskPool sync.Pool 21 | taskChan = make(chan *Task, runtime.NumCPU()) 22 | taskState = make(map[string]string) 23 | ) 24 | 25 | type Task struct { 26 | Param map[string]interface{} 27 | Factory []FacFunc 28 | UUID string 29 | Expiration int64 30 | } 31 | 32 | type FacFunc func(string, map[string]interface{}) (string, error) 33 | 34 | func NewTask(param map[string]interface{}, factory []FacFunc, d time.Duration) *Task { 35 | 36 | var expiration int64 37 | if d > 0 { 38 | expiration = time.Now().Add(d).UnixNano() 39 | } else { 40 | expiration = -1 41 | } 42 | 43 | t := taskPool.Get() 44 | if t == nil { 45 | return &Task{ 46 | param, 47 | factory, 48 | getUUID(20), 49 | expiration, 50 | } 51 | } else { 52 | task := t.(*Task) 53 | (*task).Param = param 54 | (*task).Factory = factory 55 | (*task).UUID = getUUID(20) 56 | (*task).Expiration = expiration 57 | return task 58 | } 59 | 60 | } 61 | 62 | func AddTask(task *Task) string { 63 | go func() { 64 | taskChan <- task 65 | }() 66 | uuid := (*task).UUID 67 | UpdateTaskState(uuid, StateWaiting) 68 | return uuid 69 | } 70 | 71 | func UpdateTaskState(uuid, state string) { 72 | taskStateMutex.Lock() 73 | defer taskStateMutex.Unlock() 74 | 75 | taskState[uuid] = state 76 | } 77 | 78 | func GetTaskState(uuid string) (state string) { 79 | taskStateMutex.Lock() 80 | defer taskStateMutex.Unlock() 81 | 82 | resultState, exists := taskState[uuid] 83 | if !exists { 84 | state = StateNone 85 | } else { 86 | state = resultState 87 | } 88 | return 89 | } 90 | 91 | func taskReceiver() { 92 | var taskUUID string 93 | var err error 94 | for { 95 | task := <-taskChan 96 | 97 | if ((*task).Expiration > 0 && time.Now().UnixNano() < (*task).Expiration) || (*task).Expiration < 0 { 98 | for _, f := range (*task).Factory { 99 | taskUUID, err = f((*task).UUID, (*task).Param) 100 | } 101 | if err != nil { 102 | UpdateTaskState(taskUUID, StateError) 103 | taskPool.Put(task) 104 | } else { 105 | UpdateTaskState(taskUUID, StateCompleted) 106 | taskPool.Put(task) 107 | } 108 | } else { 109 | UpdateTaskState(taskUUID, StateOverdue) 110 | taskPool.Put(task) 111 | } 112 | } 113 | } 114 | 115 | func InitTaskReceiver(num int) { 116 | for i := 0; i < num; i++ { 117 | go taskReceiver() 118 | } 119 | } 120 | 121 | func getUUID(length int64) string { 122 | ele := []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "v", "k", 123 | "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", 124 | "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"} 125 | ele, _ = random(ele) 126 | uuid := "" 127 | rand.Seed(time.Now().UnixNano()) 128 | var i int64 129 | for i = 0; i < length; i++ { 130 | uuid += ele[rand.Intn(59)] 131 | } 132 | return uuid 133 | } 134 | 135 | func random(strings []string) ([]string, error) { 136 | rand.Seed(time.Now().UnixNano()) 137 | for i := len(strings) - 1; i > 0; i-- { 138 | num := rand.Intn(i + 1) 139 | strings[i], strings[num] = strings[num], strings[i] 140 | } 141 | 142 | str := make([]string, 0) 143 | for i := 0; i < len(strings); i++ { 144 | str = append(str, strings[i]) 145 | } 146 | return str, nil 147 | } 148 | --------------------------------------------------------------------------------