├── go.mod ├── go.sum ├── task_test.go ├── README.md ├── example.go └── task.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/hubin1986/taskDepend/v2 2 | 3 | go 1.22.2 4 | 5 | require ( 6 | github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect 7 | github.com/panjf2000/ants v1.2.1 // indirect 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c= 2 | github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM= 3 | github.com/panjf2000/ants v1.2.1 h1:IlhLREssFi+YFOITnHdH3FHhulY6WDS0OB9e7+3fMHk= 4 | github.com/panjf2000/ants v1.2.1/go.mod h1:AaACblRPzq35m1g3enqYcxspbbiOJJYaxU2wMpm1cXY= 5 | github.com/panjf2000/ants v1.3.0 h1:8pQ+8leaLc9lys2viEEr8md0U4RN6uOSUCE9bOYjQ9M= 6 | github.com/panjf2000/ants v1.3.0/go.mod h1:AaACblRPzq35m1g3enqYcxspbbiOJJYaxU2wMpm1cXY= 7 | -------------------------------------------------------------------------------- /task_test.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCreateExecute(t *testing.T) { 8 | taskExecute := CreateExecute() 9 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 10 | taskB := taskExecute.CreatTask("TaskB", &TaskB{}) 11 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 12 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 13 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 14 | taskB.TaskDepend(taskA) 15 | taskB.TaskDepend(taskC) 16 | taskD.TaskDepend(taskB) 17 | taskE.TaskDepend(taskD) 18 | taskE.SetTimeout(50) 19 | taskExecute.DoExecute() 20 | 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # task depend 2 | A task execution framework based on Directed Acyclic Graph (DAG), which automatically handles complex 3 | task relationships through a simple API and provides comprehensive error handling, timeout handling, 4 | and coroutine pool processing mechanisms 5 | 6 | ## usage 7 | 8 | Import the package: 9 | 10 | ```go 11 | import ( 12 | "github.com/hubin1986/TaskDepend/v2" 13 | ) 14 | 15 | ``` 16 | 17 | ```bash 18 | go get "github.com/hubin1986/TaskDepend/v2" 19 | ``` 20 | 21 | The package is now imported under the "task" namespace. 22 | 23 | 24 | # example 25 | B depend A 26 | B depend C 27 | D depend B 28 | E depend D 29 | 30 | taskExecute := CreateExecute() 31 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 32 | taskB := taskExecute.CreatTask("TaskB", &TaskB{}) 33 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 34 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 35 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 36 | taskB.TaskDepend(taskA) 37 | taskB.TaskDepend(taskC) 38 | taskD.TaskDepend(taskB) 39 | taskE.TaskDepend(taskD) 40 | taskE.SetTimeout(50) 41 | taskExecute.DoExecute() 42 | fmt.Println("isDone TaskD:", taskD.IsDone()) 43 | fmt.Println("isDone TaskE:", taskE.IsDone()) 44 | 45 | -------------------------------------------------------------------------------- /example.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "time" 7 | ) 8 | 9 | type TaskA struct { 10 | } 11 | 12 | func (p *TaskA) Execute(node *TaskNode) bool { 13 | time.Sleep(100 * time.Millisecond) 14 | return true 15 | } 16 | 17 | func (p *TaskA) GetResult() interface{} { 18 | return "TaskA" 19 | } 20 | 21 | type TaskB struct { 22 | result string 23 | } 24 | 25 | // 方法 26 | func (p *TaskB) Execute(node *TaskNode) bool { 27 | time.Sleep(500 * time.Millisecond) 28 | p.result = "B" 29 | //return true 30 | return true 31 | } 32 | 33 | // 接口 34 | func (p *TaskB) GetResult() interface{} { 35 | return p.result 36 | } 37 | 38 | type TaskFail struct { 39 | result string 40 | } 41 | 42 | // 方法 43 | func (p *TaskFail) Execute(node *TaskNode) bool { 44 | time.Sleep(500 * time.Millisecond) 45 | p.result = "B" 46 | //return true 47 | return false 48 | } 49 | 50 | // 接口 51 | func (p *TaskFail) GetResult() interface{} { 52 | return p.result 53 | } 54 | 55 | type TaskC struct { 56 | } 57 | 58 | // 方法 59 | func (p *TaskC) Execute(node *TaskNode) bool { 60 | time.Sleep(100 * time.Millisecond) 61 | return true 62 | } 63 | 64 | // 接口 65 | func (p *TaskC) GetResult() interface{} { 66 | return "TaskC" 67 | } 68 | 69 | type TaskD struct { 70 | } 71 | 72 | // 方法 73 | func (p *TaskD) Execute(node *TaskNode) bool { 74 | time.Sleep(100 * time.Millisecond) 75 | result := node.GetResutlt("TaskB") 76 | fmt.Fprintln(os.Stdout, []any{"resutB:%v", result}...) 77 | return true 78 | } 79 | 80 | // 接口 81 | func (p *TaskD) GetResult() interface{} { 82 | return "TaskD" 83 | } 84 | 85 | type TaskE struct { 86 | } 87 | 88 | // 方法 89 | func (p *TaskE) Execute(node *TaskNode) bool { 90 | time.Sleep(100 * time.Millisecond) 91 | result := node.GetResutlt("taskD") 92 | taskD := node.GetWaitNode("taskD") 93 | fmt.Fprintln(os.Stdout, []any{"resultD:%v:", result}...) 94 | var a []any = []any{"taskD time:%d:", taskD.GetExecuteTime()} 95 | fmt.Fprintln(os.Stdout, a...) 96 | return true 97 | } 98 | 99 | // 接口 100 | func (p *TaskE) GetResult() interface{} { 101 | return "TaskE" 102 | } 103 | 104 | /** 105 | * 单任务超时 106 | * taskE.SetTimeout(500) 107 | */ 108 | func Example1() { 109 | taskExecute := CreateExecute() 110 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 111 | taskB := taskExecute.CreatTask("TaskB", &TaskB{}) 112 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 113 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 114 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 115 | taskB.TaskDepend(taskA) 116 | taskB.TaskDepend(taskC) 117 | taskD.TaskDepend(taskB) 118 | taskE.TaskDepend(taskD) 119 | taskE.SetTimeout(50) 120 | //fmt.Println("hello word") 121 | fmt.Println(taskA) 122 | fmt.Println(taskB) 123 | fmt.Println(taskC) 124 | fmt.Println(taskD) 125 | fmt.Println(taskE) 126 | taskExecute.DoExecute() 127 | fmt.Println("isDone TaskD:", taskD.IsDone()) 128 | fmt.Println("isDone TaskE:", taskE.IsDone()) 129 | //fmt.Println(taskA) 130 | //fmt.Println(taskB) 131 | } 132 | 133 | /** 134 | * 整体超时 135 | * taskExecute.SetTimeout(600) 136 | */ 137 | func Example2() { 138 | taskExecute := CreateExecute() 139 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 140 | taskB := taskExecute.CreatTask("TaskB", &TaskB{}) 141 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 142 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 143 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 144 | taskB.TaskDepend(taskA) 145 | taskB.TaskDepend(taskC) 146 | taskD.TaskDepend(taskB) 147 | taskE.TaskDepend(taskD) 148 | taskExecute.SetTimeout(1200) 149 | //fmt.Println("hello word") 150 | fmt.Println(taskA) 151 | fmt.Println(taskB) 152 | fmt.Println(taskC) 153 | fmt.Println(taskD) 154 | fmt.Println(taskE) 155 | taskExecute.DoExecute() 156 | //fmt.Println(taskA) 157 | //fmt.Println(taskB) 158 | } 159 | 160 | /** 161 | * 异常检测 162 | */ 163 | func Example3() { 164 | taskExecute := CreateExecute() 165 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 166 | err := taskA.TaskDepend(taskA) 167 | if nil != err { 168 | fmt.Println(err) 169 | } 170 | err = taskA.TaskDepend(nil) 171 | if nil != err { 172 | fmt.Println(err) 173 | } 174 | err = taskA.TaskDependName("not exist") 175 | if nil != err { 176 | fmt.Println(err) 177 | } 178 | } 179 | 180 | /** 181 | * panic test 182 | */ 183 | func Example4() { 184 | taskExecute := CreateExecute() 185 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 186 | taskB := taskExecute.CreatTask("TaskB", &TaskB{}) 187 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 188 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 189 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 190 | //taskB.TaskDependName("TaskA") 191 | //taskB.TaskDependName("TaskB") 192 | //taskD.TaskDependName("taskC") 193 | //taskE.TaskDependName("taskE") 194 | /* taskB.TaskDepend(taskA) 195 | taskB.TaskDepend(taskC) 196 | taskD.TaskDepend(taskB) 197 | taskE.TaskDepend(taskD)*/ 198 | taskExecute.SetTimeout(2000) 199 | //fmt.Println("hello word") 200 | fmt.Println(taskA) 201 | fmt.Println(taskB) 202 | fmt.Println(taskC) 203 | fmt.Println(taskD) 204 | fmt.Println(taskE) 205 | taskExecute.DoExecute() 206 | //fmt.Println(taskA) 207 | //fmt.Println(taskB) 208 | } 209 | 210 | /** 211 | * TaskDependName 212 | */ 213 | func Example5() { 214 | taskExecute := CreateExecute() 215 | taskA := taskExecute.CreatTask("taskA", &TaskA{}) 216 | taskB := taskExecute.CreatTask("taskB", &TaskB{}) 217 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 218 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 219 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 220 | taskB.TaskDependName("taskA") 221 | taskD.TaskDependName("taskB") 222 | taskD.TaskDependName("taskC") 223 | taskE.TaskDependName("taskD") 224 | taskExecute.SetTimeout(2000) 225 | //fmt.Println("hello word") 226 | fmt.Println(taskA) 227 | fmt.Println(taskB) 228 | fmt.Println(taskC) 229 | fmt.Println(taskD) 230 | fmt.Println(taskE) 231 | taskExecute.DoExecute() 232 | //fmt.Println(taskA) 233 | //fmt.Println(taskB) 234 | } 235 | 236 | /** 237 | * 网络执行器 238 | * DoExecuteGraph 239 | */ 240 | func Example6() { 241 | taskExecute := CreateExecute() 242 | taskExecute.Debug() 243 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 244 | taskB := taskExecute.CreatTask("TaskB", &TaskB{}) 245 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 246 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 247 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 248 | taskB.TaskDepend(taskA) 249 | taskB.TaskDepend(taskC) 250 | taskD.TaskDepend(taskB) 251 | taskE.TaskDepend(taskD) 252 | taskExecute.SetTimeout(1200) 253 | //fmt.Println("hello word") 254 | //fmt.Println(taskA) 255 | //fmt.Println(taskB) 256 | //fmt.Println(taskC) 257 | //fmt.Println(taskD) 258 | //fmt.Println(taskE) 259 | taskExecute.DoExecuteGraph() 260 | //fmt.Println(taskA) 261 | //fmt.Println(taskB) 262 | } 263 | 264 | /** 265 | * 整体超时 266 | * taskExecute.SetTimeout(600) 267 | */ 268 | func Example7() { 269 | taskExecute := CreateExecute() 270 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 271 | taskB := taskExecute.CreatTask("TaskB", &TaskB{}) 272 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 273 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 274 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 275 | taskB.TaskDepend(taskA) 276 | taskB.SetTimeout(20) 277 | taskB.taskTypeFailNotifyChildCancel() //当任务失败或超时时通知子节点不要执行 278 | taskB.TaskDepend(taskC) 279 | taskD.TaskDepend(taskB) 280 | taskE.TaskDepend(taskD) 281 | //taskExecute.SetTimeout(1200) 282 | //fmt.Println("hello word") 283 | fmt.Println(taskA) 284 | fmt.Println(taskB) 285 | fmt.Println(taskC) 286 | fmt.Println(taskD) 287 | fmt.Println(taskE) 288 | taskExecute.DoExecuteGraph() 289 | //fmt.Println(taskA) 290 | //fmt.Println(taskB) 291 | } 292 | 293 | /** 294 | * 整体超时,取消未执行任务 295 | * taskExecute.SetTimeout(600) 296 | */ 297 | func Example8() { 298 | taskExecute := CreateExecute() 299 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 300 | taskB := taskExecute.CreatTask("TaskB", &TaskB{}) 301 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 302 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 303 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 304 | taskB.TaskDepend(taskA) 305 | //taskB.SetTimeout(20) 306 | taskB.taskTypeFailNotifyChildCancel() //当任务失败或超时时通知子节点不要执行 307 | taskB.TaskDepend(taskC) 308 | taskD.TaskDepend(taskB) 309 | taskE.TaskDepend(taskD) 310 | taskExecute.SetTimeout(590) 311 | //fmt.Println("hello word") 312 | fmt.Println(taskA) 313 | fmt.Println(taskB) 314 | fmt.Println(taskC) 315 | fmt.Println(taskD) 316 | fmt.Println(taskE) 317 | taskExecute.DoExecuteGraph() 318 | //fmt.Println(taskA) 319 | //fmt.Println(taskB) 320 | 321 | time.Sleep(time.Duration(3) * time.Second) 322 | } 323 | 324 | /** 325 | * 核心作业失败 326 | */ 327 | func Example9() { 328 | taskExecute := CreateExecute() 329 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 330 | taskB := taskExecute.CreatTask("TaskB", &TaskFail{}) 331 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 332 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 333 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 334 | taskB.TaskDepend(taskA) 335 | //taskB.SetTimeout(20) 336 | taskB.taskTypeFailCoreFail() 337 | taskB.TaskDepend(taskC) 338 | taskD.TaskDepend(taskB) 339 | taskE.TaskDepend(taskD) 340 | //taskExecute.SetTimeout(590) 341 | //fmt.Println("hello word") 342 | fmt.Println(taskA) 343 | fmt.Println(taskB) 344 | fmt.Println(taskC) 345 | fmt.Println(taskD) 346 | fmt.Println(taskE) 347 | taskExecute.DoExecuteGraph() 348 | //fmt.Println(taskA) 349 | //fmt.Println(taskB) 350 | 351 | time.Sleep(time.Duration(3) * time.Second) 352 | } 353 | 354 | /** 355 | * 打印执行过程,deadlock检测 356 | */ 357 | func Example10() { 358 | taskExecute := CreateExecute() 359 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 360 | taskB := taskExecute.CreatTask("TaskB", &TaskFail{}) 361 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 362 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 363 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 364 | taskB.TaskDepend(taskA) 365 | taskB.TaskDepend(taskC) 366 | taskD.TaskDepend(taskB) 367 | taskE.TaskDepend(taskD) 368 | //deadlock 369 | taskA.TaskDepend(taskD) 370 | //taskExecute.SetTimeout(590) 371 | //fmt.Println("hello word") 372 | 373 | taskExecute.printExecureGraph() 374 | //fmt.Println(taskA) 375 | //fmt.Println(taskB) 376 | 377 | time.Sleep(time.Duration(3) * time.Second) 378 | } 379 | 380 | /** 381 | * TaskDependGroup 382 | */ 383 | func Example11() { 384 | taskExecute := CreateExecute() 385 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 386 | taskB := taskExecute.CreatTask("TaskB", &TaskFail{}) 387 | //taskC := taskExecute.CreatTask("taskC", &TaskC{}) 388 | taskExecute.CreatTask("taskC", &TaskC{}) 389 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 390 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 391 | //taskB.TaskDepend(taskA) 392 | //taskB.TaskDepend(taskC) 393 | taskB.TaskDependGroup([]string{"TaskA", "taskC"}...) 394 | taskD.TaskDepend(taskB) 395 | taskE.TaskDepend(taskD) 396 | //deadlock 397 | taskA.TaskDepend(taskD) 398 | //taskExecute.SetTimeout(590) 399 | //fmt.Println("hello word") 400 | //taskExecute.NewPool(1) 401 | taskExecute.printExecureGraph() 402 | //fmt.Println(taskA) 403 | //fmt.Println(taskB) 404 | 405 | time.Sleep(time.Duration(3) * time.Second) 406 | } 407 | 408 | /** 409 | * NewPool 支持协程池 410 | */ 411 | func Example12() { 412 | taskExecute := CreateExecute() 413 | taskExecute.Debug() 414 | taskExecute.NewPool(1) 415 | taskA := taskExecute.CreatTask("TaskA", &TaskA{}) 416 | taskB := taskExecute.CreatTask("TaskB", &TaskB{}) 417 | taskC := taskExecute.CreatTask("taskC", &TaskC{}) 418 | taskD := taskExecute.CreatTask("taskD", &TaskD{}) 419 | taskE := taskExecute.CreatTask("taskE", &TaskE{}) 420 | taskB.TaskDepend(taskA) 421 | taskB.TaskDepend(taskC) 422 | taskD.TaskDepend(taskB) 423 | taskE.TaskDepend(taskD) 424 | taskExecute.SetTimeout(1200) 425 | //fmt.Println("hello word") 426 | //fmt.Println(taskA) 427 | //fmt.Println(taskB) 428 | //fmt.Println(taskC) 429 | //fmt.Println(taskD) 430 | //fmt.Println(taskE) 431 | taskExecute.DoExecuteGraph() 432 | } 433 | -------------------------------------------------------------------------------- /task.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "runtime/debug" 7 | "sort" 8 | "strconv" 9 | "sync/atomic" 10 | "time" 11 | 12 | cmap "github.com/orcaman/concurrent-map/v2" 13 | "github.com/panjf2000/ants" 14 | ) 15 | 16 | const DEFALUT_TASK_TIMEOUT = 1500 17 | const DEFALUT_EXECUTE_TIMEOUT = 1500 18 | const ROOT_NODE = "root" 19 | const FINAL_NODE = "final_node" 20 | 21 | // signal 22 | const SIGNAL_TASK_DONE = 1 23 | const SIGNAL_TASK_PANIC = 2 24 | const SIGNAL_TASK_FAIL = 3 25 | const SIGNAL_TASK_FAIL_WAIT_NODE = 4 26 | 27 | // ERROR_CODE 28 | const ERROR_NO_NULL_DEPEND = 1 29 | const ERROR_NO_SELF_DEPEND = 2 30 | const ERROR_NO_TASK_ERROR = 3 31 | const ERROR_NO_TASK_PANIC = 4 32 | const ERROR_NO_TASK_TIMEOUT = 5 33 | const ERROR_NO_EXECUTE_TIMEOUT = 6 34 | const ERROR_NO_TASK_FAIL_WAIT_ERROR = 7 35 | 36 | // ERROR_MSG 37 | const ERROR_MSG_NULL_DEPEND = "can not depend nil" 38 | const ERROR_MSG_SELF_DEPEND = "can not depend itself" 39 | const ERROR_MSG_TASK_ERROR = "task fail" 40 | const ERROR_MSG_TASK_PANIC = "task panic" 41 | const ERROR_MSG_TASK_TIMEOUT = "task timeout" 42 | const ERROR_MSG_EXECUTE_TIMEOUT = "execute timeout" 43 | const ERROR_MSG_TASK_FAIL_WAIT_ERROR = "task wait node error" 44 | 45 | // 任务状态 46 | const TASK_STATUS_INTI = 0 47 | const TASK_STATUS_RUNNING = 1 48 | const TASK_STATUS_SUCCESS = 2 49 | const TASK_STATUS_TIMEOUT = 3 50 | const TASK_STATUS_ERROR = 4 51 | const TASK_STATUS_WAIT_NODE_FAIL = 5 //父节点失败 52 | 53 | // task 任务类型 54 | const TASK_TYPE_DEFAULT = 0 //默认任务类型 55 | const TASK_TYPE_FAIL_NOTIFY_CHILD_CANCEL = 1 //当前节点失败后通知子节点不用做处理了 56 | const TASK_TYPE_FAIL_CORE_FAIL = 2 //核心任务,如果失败认为整体失败 57 | 58 | // 最小携程池并行度,理论上是2 59 | const MINI_POOL_SIZE = 2 60 | 61 | type Error struct { 62 | ErrCode int 63 | ErrMsg string 64 | } 65 | 66 | func CreateError(code int, msg string) *Error { 67 | return &Error{ErrCode: code, ErrMsg: msg} 68 | } 69 | 70 | func (err *Error) Error() string { 71 | return err.ErrMsg 72 | } 73 | 74 | // root task 75 | type RootTask struct { 76 | } 77 | 78 | // executor of task 79 | func (this *RootTask) Execute(node *TaskNode) bool { 80 | node.execute.startTime = time.Now().UnixNano() / 1e6 81 | return true 82 | } 83 | 84 | // result of task 85 | func (this *RootTask) GetResult() interface{} { 86 | return "" 87 | } 88 | 89 | // 最后运行的系统作业 90 | type FinalizeTask struct { 91 | } 92 | 93 | // 方法 94 | func (this *FinalizeTask) Execute(node *TaskNode) bool { 95 | //fmt.Println("") 96 | node.execute.endTime = time.Now().UnixNano() / 1e6 97 | node.execute.executeTime = node.execute.endTime - node.execute.startTime 98 | //所有任务完成 99 | node.execute.isDoneChan <- 1 100 | return true 101 | } 102 | 103 | // 接口 104 | func (this *FinalizeTask) GetResult() interface{} { 105 | return "" 106 | } 107 | 108 | type Queue interface { 109 | Offer(e interface{}) 110 | Poll() interface{} 111 | Watch() interface{} 112 | Clear() bool 113 | Size() int 114 | IsEmpty() bool 115 | } 116 | 117 | type LinkedList struct { 118 | index int 119 | elements []interface{} 120 | } 121 | 122 | func CreateQueue() *LinkedList { 123 | return &LinkedList{} 124 | } 125 | 126 | func (queue *LinkedList) Offer(e interface{}) { 127 | queue.elements = append(queue.elements, e) 128 | } 129 | 130 | func (queue *LinkedList) Watch() interface{} { 131 | if queue.IsEmpty() { 132 | return nil 133 | } 134 | //firstElement := queue.elements[0] 135 | curElement := queue.elements[queue.index] 136 | return curElement 137 | } 138 | 139 | func (queue *LinkedList) Next() interface{} { 140 | if queue.IsEmpty() { 141 | return nil 142 | } 143 | firstElement := queue.elements[queue.index] 144 | queue.index = (queue.index + 1) % queue.Size() 145 | return firstElement 146 | } 147 | 148 | func (queue *LinkedList) Poll() interface{} { 149 | if queue.IsEmpty() { 150 | //.Println("Poll error : queue is Empty") 151 | return nil 152 | } 153 | 154 | if queue.index == 0 { 155 | firstElement := queue.elements[0] 156 | queue.elements = queue.elements[1:] 157 | return firstElement 158 | } 159 | 160 | curElement := queue.elements[queue.index] 161 | head := queue.elements[0:queue.index] 162 | tail := queue.elements[queue.index+1:] 163 | if queue.index > 0 { 164 | queue.index = queue.index - 1 165 | } 166 | queue.elements = append(head, tail...) 167 | 168 | return curElement 169 | } 170 | 171 | func (queue *LinkedList) Size() int { 172 | return len(queue.elements) 173 | } 174 | 175 | func (queue *LinkedList) IsEmpty() bool { 176 | return len(queue.elements) == 0 177 | } 178 | 179 | func (queue *LinkedList) Clear() bool { 180 | if queue.IsEmpty() { 181 | //fmt.Println("queue is Empty!") 182 | return false 183 | } 184 | for i := 0; i < queue.Size(); i++ { 185 | queue.elements[i] = nil 186 | } 187 | queue.elements = nil 188 | return true 189 | } 190 | 191 | type Worker interface { 192 | Execute(node *TaskNode) bool 193 | GetResult() interface{} 194 | } 195 | 196 | // worker 197 | type TaskNode struct { 198 | name string 199 | taskType int32 //任务类型 200 | status int32 //0,任务未执行,1,任务已执行 201 | notifyNumber int32 202 | waitNumber int32 203 | waitList []*TaskNode 204 | notifyList []*TaskNode 205 | waitMap map[string]*TaskNode 206 | notifyMap map[string]string 207 | 208 | isInQueue int32 209 | 210 | worker Worker 211 | execute *TaskExecute 212 | executeTime int64 213 | startTime int64 214 | endTime int64 215 | timeOut int64 216 | errno int32 217 | errmsg string 218 | isError bool 219 | isTimeOut bool 220 | isDone bool 221 | isPrintDone bool //print执行时 222 | } 223 | 224 | // task executor 225 | type TaskExecute struct { 226 | root *TaskNode 227 | finalNode *TaskNode 228 | taskList []*TaskNode 229 | taskMap map[string]*TaskNode 230 | undoNumber int32 231 | queue *LinkedList 232 | executeList *LinkedList 233 | readyChan chan string 234 | isDoneChan chan int 235 | 236 | startTime int64 237 | endTime int64 238 | executeTime int64 239 | timeOut int64 240 | isError bool 241 | isTimeOut bool 242 | isDone bool 243 | 244 | isCancel bool 245 | 246 | logMap cmap.ConcurrentMap[string, string] 247 | warnLogMap cmap.ConcurrentMap[string, string] 248 | hasLog bool 249 | hasWarnLog bool 250 | 251 | printExecuteStruct bool //打印执行过程结构 252 | isDebug bool //debug 模式 253 | 254 | usePool bool //使用协程池 255 | poolSize int //协程池数量 256 | pool *ants.Pool //协程池 257 | } 258 | 259 | /* 260 | * 261 | 创建任务执行器 262 | */ 263 | func CreateExecute() *TaskExecute { 264 | execute := new(TaskExecute) 265 | execute.taskList = make([]*TaskNode, 0, 10) 266 | execute.taskMap = make(map[string]*TaskNode, 10) 267 | execute.root = execute.CreatTask(ROOT_NODE, &RootTask{}) 268 | execute.finalNode = execute.CreatTask(FINAL_NODE, &FinalizeTask{}) 269 | execute.queue = CreateQueue() 270 | execute.executeList = CreateQueue() 271 | execute.timeOut = DEFALUT_EXECUTE_TIMEOUT 272 | execute.isDoneChan = make(chan int, 1) 273 | execute.isTimeOut = false 274 | execute.isDone = false 275 | execute.isCancel = false 276 | execute.isError = false 277 | execute.logMap = cmap.New[string]() 278 | execute.warnLogMap = cmap.New[string]() 279 | execute.hasLog = false 280 | execute.hasWarnLog = false 281 | execute.printExecuteStruct = false 282 | execute.isDebug = false 283 | execute.usePool = false 284 | execute.poolSize = 0 285 | return execute 286 | } 287 | 288 | type taskNodePointer *TaskNode 289 | 290 | /** 291 | * 设置debug 292 | */ 293 | func (execute *TaskExecute) Debug() { 294 | execute.isDebug = true 295 | } 296 | 297 | /** 298 | * 使用协程池 299 | */ 300 | func (execute *TaskExecute) NewPool(poolSize int) { 301 | execute.usePool = true 302 | 303 | poolSize = poolSize + MINI_POOL_SIZE 304 | 305 | execute.poolSize = poolSize 306 | pool, error := ants.NewPool(poolSize) //新建一个pool对象,其他同上 307 | if nil != error { 308 | execute.pool = pool 309 | } 310 | } 311 | 312 | /** 313 | * 释放协程池 314 | */ 315 | func (execute *TaskExecute) ReleasePool() { 316 | if execute.usePool && nil != execute.pool { 317 | execute.pool.Release() 318 | } 319 | } 320 | 321 | /** 322 | * 日志debug 323 | */ 324 | func (execute *TaskExecute) logDebug(format string, a ...interface{}) { 325 | log := "Debug:" + format 326 | now := time.Now().UnixNano() 327 | prefix := strconv.FormatInt(now, 10) 328 | execute.hasLog = true 329 | execute.logMap.Set(prefix, fmt.Sprintf(log, a)) 330 | if execute.printExecuteStruct || execute.isDebug { 331 | fmt.Println(log, a) 332 | } 333 | } 334 | 335 | /** 336 | * 日志notice 337 | */ 338 | func (execute *TaskExecute) logNotice(format string, a ...interface{}) { 339 | log := "Notice:" + format 340 | now := time.Now().UnixNano() 341 | prefix := strconv.FormatInt(now, 10) 342 | execute.hasLog = true 343 | execute.logMap.Set(prefix, fmt.Sprintf(log, a)) 344 | if execute.printExecuteStruct || execute.isDebug { 345 | fmt.Println(log, a) 346 | } 347 | } 348 | 349 | /** 350 | * 日志warn 351 | */ 352 | func (execute *TaskExecute) logWarn(format string, a ...interface{}) { 353 | log := "Warn:" + format 354 | now := time.Now().UnixNano() 355 | prefix := strconv.FormatInt(now, 10) 356 | execute.hasWarnLog = true 357 | execute.warnLogMap.Set(prefix, fmt.Sprintf(log, a)) 358 | if execute.printExecuteStruct || execute.isDebug { 359 | fmt.Println(log, a) 360 | } 361 | } 362 | 363 | /** 364 | * 日志fatal 365 | */ 366 | func (execute *TaskExecute) logFatal(format string, a ...interface{}) { 367 | log := "Fatal:" + format 368 | now := time.Now().UnixNano() 369 | prefix := strconv.FormatInt(now, 10) 370 | execute.hasWarnLog = true 371 | execute.warnLogMap.Set(prefix, fmt.Sprintf(log, a)) 372 | if execute.printExecuteStruct || execute.isDebug { 373 | fmt.Println(log, a) 374 | } 375 | } 376 | 377 | /** 378 | * 打印日志 379 | */ 380 | func (execute *TaskExecute) PrintLog(logFunc func(log string)) { 381 | if !execute.hasLog { 382 | return 383 | } 384 | execute.sortLogPrint(execute.logMap, logFunc) 385 | } 386 | 387 | /** 388 | * 打印warn,fatal日志 389 | */ 390 | func (execute *TaskExecute) PrintWarnLog(logFunc func(log string)) { 391 | if !execute.hasWarnLog { 392 | return 393 | } 394 | execute.sortLogPrint(execute.warnLogMap, logFunc) 395 | } 396 | 397 | /** 398 | * task 状态数据 399 | */ 400 | func (execute *TaskExecute) StatisticTask(taskFunc func(task *TaskNode)) { 401 | if execute.taskList != nil && len(execute.taskList) > 0 { 402 | for _, task := range execute.taskList { 403 | if nil != task { 404 | taskFunc(task) 405 | } 406 | } 407 | } 408 | } 409 | 410 | /** 411 | * 日志排序 412 | */ 413 | func (execute *TaskExecute) sortLogPrint(logMap cmap.ConcurrentMap[string, string], logFunc func(log string)) { 414 | m := make(map[string]string) 415 | var keys []string 416 | 417 | logMap.IterCb(func(key string, v string) { 418 | m[key] = v 419 | keys = append(keys, key) 420 | 421 | }) 422 | 423 | sort.Strings(keys) 424 | 425 | prefix := "taskDepend" 426 | for _, k := range keys { 427 | logFunc(prefix + m[k]) 428 | } 429 | } 430 | 431 | /** 432 | * 图执行过程 433 | */ 434 | func (execute *TaskExecute) printExecureGraph() { 435 | execute.printExecuteStruct = true 436 | execute.DoExecuteGraph() 437 | if execute.taskList != nil { 438 | for _, task := range execute.taskList { 439 | if false == task.isPrintDone { 440 | execute.logDebug("deadlock:", task.GetTaskName()) 441 | } 442 | } 443 | } 444 | } 445 | 446 | /** 447 | * final添加依赖 448 | */ 449 | func (execute *TaskExecute) finalDepend() { 450 | if execute.finalNode != nil { 451 | for _, node := range execute.taskList { 452 | if node.notifyNumber == 0 { 453 | execute.finalNode.TaskDepend(node) 454 | } 455 | } 456 | 457 | execute.taskList = append(execute.taskList, execute.finalNode) 458 | } 459 | } 460 | 461 | /** 462 | * 添加依赖的任务数 463 | */ 464 | func (execute *TaskExecute) AddUndoNumber(delta int32) { 465 | atomic.AddInt32(&execute.undoNumber, delta) 466 | } 467 | 468 | /** 469 | * 超时设置 470 | */ 471 | func (execute *TaskExecute) SetTimeout(timeOut int64) { 472 | execute.timeOut = timeOut 473 | } 474 | 475 | /* 476 | * 477 | 478 | execute是否成功 479 | */ 480 | func (execute *TaskExecute) IsDone() bool { 481 | return execute.isDone 482 | } 483 | 484 | /* 485 | * 486 | 创建任务 487 | */ 488 | func (execute *TaskExecute) CreatTask(name string, worker Worker) *TaskNode { 489 | task := new(TaskNode) 490 | task.name = name 491 | task.taskType = TASK_TYPE_DEFAULT 492 | task.status = TASK_STATUS_INTI 493 | task.notifyList = make([]*TaskNode, 0, 10) 494 | task.waitList = make([]*TaskNode, 0, 10) 495 | task.waitMap = make(map[string]*TaskNode, 10) 496 | task.notifyMap = make(map[string]string, 10) 497 | task.worker = worker 498 | task.execute = execute 499 | task.errmsg = "" 500 | task.timeOut = DEFALUT_TASK_TIMEOUT 501 | task.isTimeOut = false 502 | task.isDone = false 503 | task.isError = false 504 | task.isPrintDone = false 505 | //先关联tasklist 506 | if name != ROOT_NODE && name != FINAL_NODE { 507 | execute.taskList = append(execute.taskList, task) 508 | execute.taskMap[name] = task 509 | } 510 | //fmt.Println("creatTask:",execute.taskList) 511 | return task 512 | } 513 | 514 | /* 515 | * 516 | 517 | 启动线性执行器 518 | */ 519 | func (this *TaskExecute) DoExecute() error { 520 | //finaldepend 521 | this.finalDepend() 522 | go this.DoExecuteWrap() 523 | select { 524 | case <-this.isDoneChan: 525 | //fmt.Println("isDone") 526 | this.logNotice("DoExecute isDone") 527 | this.isDone = true 528 | case <-time.After(time.Millisecond * time.Duration(this.timeOut)): 529 | // timeout 超时 530 | //fmt.Println("allTimeout") 531 | this.logWarn("DoExecute allTimeout") 532 | this.isTimeOut = true 533 | } 534 | 535 | if this.isTimeOut == true { 536 | return CreateError(ERROR_NO_EXECUTE_TIMEOUT, ERROR_MSG_EXECUTE_TIMEOUT) 537 | } 538 | 539 | return nil 540 | } 541 | 542 | // 线性执行器 543 | func (this *TaskExecute) DoExecuteWrap() { 544 | defer func() { 545 | if err := recover(); nil != err { 546 | log.Printf("TaskExecute DoExecuteWrap panic, err:%v\n", err) 547 | } 548 | }() 549 | //如果任务没有依赖关联root 550 | for _, node := range this.taskList { 551 | if len(node.waitList) == 0 { 552 | node.TaskDepend(this.root) 553 | } 554 | } 555 | this.queue.Offer(this.root) 556 | this.logDebug("offer root") 557 | for !this.queue.IsEmpty() { 558 | visit := this.queue.Poll().(*TaskNode) 559 | this.executeList.Offer(visit) 560 | //不存在并发 561 | this.undoNumber = this.undoNumber + 1 562 | this.logDebug("visit:", visit.GetTaskName()) 563 | //this.queue.Poll() 564 | 565 | if visit.notifyNumber > 0 { 566 | for _, node := range visit.notifyList { 567 | //fmt.Println(node.GetTaskName()) 568 | if node.isInQueue == 0 { 569 | this.queue.Offer(node) 570 | node.isInQueue = 1 571 | } 572 | } 573 | } 574 | } 575 | this.readyChan = make(chan string, this.undoNumber) 576 | isRootRun := 1 577 | for this.undoNumber > 0 { 578 | node, ok := this.executeList.Watch().(*TaskNode) 579 | if !ok { 580 | break 581 | } 582 | 583 | skipLength := this.executeList.Size() 584 | for ; skipLength > 0 && !this.executeList.IsEmpty(); node, ok = this.executeList.Watch().(*TaskNode) { 585 | if !ok { 586 | break 587 | } 588 | 589 | if isRootRun != 1 { 590 | for { 591 | select { 592 | case ready := <-this.readyChan: 593 | this.logDebug("ready to run: %s\n", ready) 594 | } 595 | break 596 | } 597 | } 598 | 599 | isRootRun = 0 600 | 601 | if node.waitNumber == 0 { 602 | go node.Execute() 603 | this.executeList.Poll() 604 | //this.executeList.Next() 605 | } else { 606 | this.executeList.Next() 607 | //noop 608 | } 609 | skipLength-- 610 | } 611 | 612 | } 613 | } 614 | 615 | /* 616 | * 617 | 618 | execute 后执行资源释放 619 | */ 620 | func (this *TaskExecute) finalize() { 621 | //如果有协程池则释放 622 | this.ReleasePool() 623 | } 624 | 625 | /* 626 | * 627 | 628 | 启动图执行器 629 | */ 630 | func (this *TaskExecute) DoExecuteGraph() error { 631 | //释放资源 632 | this.finalize() 633 | //finaldepend 634 | this.finalDepend() 635 | this.DoExecuteWrapGraph() 636 | 637 | select { 638 | case <-this.isDoneChan: 639 | //fmt.Println("isDone") 640 | this.logDebug("DoExecuteGraph isDone") 641 | this.isDone = true 642 | case <-time.After(time.Millisecond * time.Duration(this.timeOut)): 643 | // timeout 超时 644 | //fmt.Println("allTimeout") 645 | this.logWarn("DoExecuteGraph allTimeout:%d", this.timeOut) 646 | this.isTimeOut = true 647 | } 648 | 649 | if this.isTimeOut == true { 650 | return CreateError(ERROR_NO_EXECUTE_TIMEOUT, ERROR_MSG_EXECUTE_TIMEOUT) 651 | } 652 | 653 | return nil 654 | } 655 | 656 | /* 657 | * 658 | 具体逻辑 659 | */ 660 | func (this *TaskExecute) DoExecuteWrapGraph() { 661 | //如果任务没有依赖关联root 662 | for _, node := range this.taskList { 663 | if len(node.waitList) == 0 { 664 | node.TaskDepend(this.root) 665 | } 666 | } 667 | if this.usePool && nil != this.pool { 668 | this.pool.Submit(func() { 669 | this.root.ExecuteGraph() 670 | }) 671 | } else { 672 | go this.root.ExecuteGraph() 673 | } 674 | //go this.root.ExecuteGraph() 675 | } 676 | 677 | /* 678 | * 679 | 680 | executor 执行时间 681 | */ 682 | func (this *TaskExecute) GetExecuteTime() int64 { 683 | return this.executeTime 684 | } 685 | 686 | /* 687 | * 688 | 689 | 是否是在协程池中执行 690 | */ 691 | func (this *TaskNode) isRunInPool() bool { 692 | if this.execute.usePool && nil != this.execute.pool { 693 | return true 694 | } 695 | return false 696 | } 697 | 698 | /* 699 | * 700 | 701 | 任务是否失败 702 | */ 703 | func (this *TaskNode) IsError() bool { 704 | return this.isError 705 | } 706 | 707 | /* 708 | * 709 | 710 | 任务是否超时 711 | */ 712 | func (this *TaskNode) IsTimeOut() bool { 713 | return this.isTimeOut 714 | } 715 | 716 | /* 717 | * 718 | 719 | 任务是否成功 720 | */ 721 | func (this *TaskNode) IsDone() bool { 722 | return this.isDone 723 | } 724 | 725 | /* 726 | * 727 | 728 | 启动执行器 729 | */ 730 | func (this *TaskNode) Execute() { 731 | defer func() { 732 | if err := recover(); nil != err { 733 | log.Printf("TaskNode Execute panic, err:%v\n", err) 734 | } 735 | }() 736 | if 0 == this.GetWaitNumber() { 737 | this.execute.AddUndoNumber(-1) 738 | done := make(chan int, 1) 739 | go this.ExecuteWrap(done) 740 | 741 | select { 742 | case taskStatus := <-done: 743 | if taskStatus == SIGNAL_TASK_DONE { 744 | //fmt.Println("call task successfully:%s", this.GetTaskName()) 745 | this.execute.logDebug("call task successfully:%s", this.GetTaskName()) 746 | this.status = TASK_STATUS_SUCCESS 747 | this.isDone = true 748 | } else if taskStatus == SIGNAL_TASK_PANIC { 749 | //fmt.Println("call task panic :", this.GetTaskName()) 750 | this.execute.logFatal("call task panic:%s", this.GetTaskName()) 751 | this.errno = ERROR_NO_TASK_PANIC 752 | this.errmsg = ERROR_MSG_TASK_ERROR 753 | this.status = TASK_STATUS_ERROR 754 | this.isError = true 755 | } else if taskStatus == SIGNAL_TASK_FAIL { 756 | //fmt.Println("call task fail :", this.GetTaskName()) 757 | this.execute.logWarn("call task fail:%s", this.GetTaskName()) 758 | this.errno = ERROR_NO_TASK_ERROR 759 | this.errmsg = ERROR_MSG_TASK_ERROR 760 | this.status = TASK_STATUS_ERROR 761 | this.isError = true 762 | } 763 | case <-time.After(time.Millisecond * time.Duration(this.timeOut)): 764 | //fmt.Println("timeout:", this.GetTaskName()) 765 | this.execute.logWarn("task timeout:%s", this.GetTaskName()) 766 | this.isTimeOut = true 767 | this.status = TASK_STATUS_TIMEOUT 768 | this.errno = ERROR_NO_TASK_TIMEOUT 769 | this.errmsg = ERROR_MSG_TASK_TIMEOUT 770 | size := len(this.notifyList) 771 | for i := 0; i < size; i++ { 772 | notifyNode := this.notifyList[i] 773 | //当waitnumer==0即进入可执行状态 774 | notifyNode.AddWaitNumber(-1) 775 | } 776 | 777 | //notifyAll 778 | //fmt.Println("notify by:", this.GetTaskName()) 779 | this.execute.logDebug("notify by:%s", this.GetTaskName()) 780 | this.execute.readyChan <- this.GetTaskName() 781 | } 782 | 783 | } 784 | 785 | } 786 | 787 | /* 788 | * 789 | 790 | 启动执行器 791 | */ 792 | func (this *TaskNode) ExecuteWrap(done chan int) { 793 | //fmt.Println("doexe:" + this.GetTaskName()) 794 | this.execute.logDebug("doexe:" + this.GetTaskName()) 795 | var startTime = time.Now() 796 | this.startTime = time.Now().UnixNano() / 1e6 797 | defer func() { 798 | if err := recover(); nil != err { 799 | this.errmsg = string(debug.Stack()) 800 | //fmt.Println(this.errmsg) 801 | this.execute.logFatal(this.errmsg + " fask fatal:" + this.errmsg) 802 | size := len(this.notifyList) 803 | for i := 0; i < size; i++ { 804 | notifyNode := this.notifyList[i] 805 | //当waitnumer==0即进入可执行状态 806 | notifyNode.AddWaitNumber(-1) 807 | } 808 | //notifyAll 809 | //fmt.Println("notify by:", this.GetTaskName()) 810 | this.execute.logDebug("notify by:" + this.GetTaskName()) 811 | this.execute.readyChan <- this.GetTaskName() 812 | done <- SIGNAL_TASK_PANIC 813 | } 814 | cost := time.Since(startTime).Milliseconds() 815 | if cost < 1 { 816 | cost = 0 817 | } 818 | this.executeTime = cost 819 | this.endTime = time.Now().UnixNano() / 1e6 820 | }() 821 | if nil != this.worker { 822 | success := this.worker.Execute(this) 823 | if !success { 824 | this.errorNotifyChild(TASK_STATUS_ERROR) 825 | done <- SIGNAL_TASK_FAIL 826 | } 827 | } 828 | //this.execute.AddUndoNumber(-1) 829 | size := len(this.notifyList) 830 | for i := 0; i < size; i++ { 831 | notifyNode := this.notifyList[i] 832 | //当waitnumer==0即进入可执行状态 833 | notifyNode.AddWaitNumber(-1) 834 | } 835 | //notifyAll 836 | //fmt.Println("notify by:", this.GetTaskName()) 837 | this.execute.logDebug("notify by:" + this.GetTaskName()) 838 | this.execute.readyChan <- this.GetTaskName() 839 | done <- SIGNAL_TASK_DONE 840 | 841 | } 842 | 843 | /* 844 | * 845 | 846 | 启动执行器 847 | */ 848 | func (this *TaskNode) ExecuteGraph() { 849 | defer func() { 850 | if err := recover(); nil != err { 851 | this.errmsg = string(debug.Stack()) 852 | //this.execute.logFatal(this.errmsg + "node ExecuteGraph fatal:"+ this.errmsg) 853 | this.execute.logFatal(this.GetTaskName() + " out task panic:" + this.errmsg) 854 | } 855 | }() 856 | //等待的任务都完成了 857 | if 0 == this.GetWaitNumber() || 858 | (this.name == FINAL_NODE && (this.execute.isTimeOut == true || this.execute.isCancel)) { //执行器超时的特殊处理逻辑 859 | //当前任务执行中 860 | if this.status == TASK_STATUS_INTI { 861 | this.status = TASK_STATUS_RUNNING 862 | } 863 | this.execute.AddUndoNumber(-1) 864 | done := make(chan int, 1) 865 | 866 | if this.isRunInPool() { 867 | this.execute.pool.Submit(func() { 868 | this.ExecuteWrapGraph(done) 869 | }) 870 | } else { 871 | go this.ExecuteWrapGraph(done) 872 | } 873 | 874 | select { 875 | case taskStatus := <-done: 876 | if taskStatus == SIGNAL_TASK_DONE { 877 | //fmt.Println("call task successfully:", this.GetTaskName()) 878 | this.execute.logDebug("call task successfully:", this.GetTaskName()) 879 | this.isDone = true 880 | this.status = TASK_STATUS_SUCCESS 881 | } else if taskStatus == SIGNAL_TASK_PANIC { 882 | //fmt.Println("call task panic :", this.GetTaskName()) 883 | this.execute.logFatal("call task panic :", this.GetTaskName()) 884 | this.errno = ERROR_NO_TASK_PANIC 885 | this.errmsg = ERROR_MSG_TASK_PANIC 886 | this.status = TASK_STATUS_ERROR 887 | this.isError = true 888 | } else if taskStatus == SIGNAL_TASK_FAIL { 889 | //fmt.Println("call task fail :", this.GetTaskName()) 890 | this.execute.logWarn("call task fail :", this.GetTaskName()) 891 | this.errno = ERROR_NO_TASK_ERROR 892 | this.errmsg = ERROR_MSG_TASK_ERROR 893 | this.status = TASK_STATUS_ERROR 894 | this.isError = true 895 | } else if taskStatus == SIGNAL_TASK_FAIL_WAIT_NODE { 896 | //fmt.Println("call task fail by wait node :", this.GetTaskName()) 897 | this.execute.logWarn("call task fail by wait node :", this.GetTaskName()) 898 | this.errno = ERROR_NO_TASK_FAIL_WAIT_ERROR 899 | this.errmsg = ERROR_MSG_TASK_FAIL_WAIT_ERROR 900 | this.status = TASK_STATUS_WAIT_NODE_FAIL 901 | this.isError = true 902 | } 903 | //notifyAll 904 | //fmt.Println("notify by:", this.GetTaskName()) 905 | this.execute.logDebug("notify by:", this.GetTaskName()) 906 | this.NotifyAll() 907 | case <-time.After(time.Millisecond * time.Duration(this.timeOut)): 908 | //fmt.Println("timeout:", this.GetTaskName()) 909 | this.execute.logWarn("timeout:", this.GetTaskName()) 910 | this.isTimeOut = true 911 | this.errno = ERROR_NO_TASK_TIMEOUT 912 | this.errmsg = ERROR_MSG_TASK_TIMEOUT 913 | this.status = TASK_STATUS_TIMEOUT 914 | this.errorNotifyChild(TASK_STATUS_TIMEOUT) 915 | this.NotifyAll() 916 | 917 | //notifyAll 918 | //fmt.Println("notify by:", this.GetTaskName()) 919 | this.execute.logDebug("notify by:", this.GetTaskName()) 920 | 921 | } 922 | 923 | } 924 | 925 | } 926 | 927 | /* 928 | * 929 | 930 | 启动执行器 931 | */ 932 | func (this *TaskNode) ExecuteWrapGraph(done chan int) { 933 | //fmt.Println("doexe:" + this.GetTaskName()) 934 | this.execute.logDebug("doexe:" + this.GetTaskName()) 935 | var startTime = time.Now() 936 | this.startTime = time.Now().UnixNano() / 1e6 937 | defer func() { 938 | if err := recover(); nil != err { 939 | this.errmsg = string(debug.Stack()) 940 | //.Println(this.errmsg) 941 | this.execute.logFatal(this.GetTaskName() + " task panic:" + this.errmsg) 942 | done <- SIGNAL_TASK_PANIC 943 | } 944 | cost := time.Since(startTime).Milliseconds() 945 | if cost < 1 { 946 | cost = 0 947 | } 948 | this.executeTime = cost 949 | this.endTime = time.Now().UnixNano() / 1e6 950 | }() 951 | 952 | //依赖的任务已经失败 953 | if this.status == TASK_STATUS_WAIT_NODE_FAIL && this.name != FINAL_NODE { 954 | //fmt.Println("failwait:", this.GetTaskName()) 955 | this.execute.logWarn("failwait:", this.GetTaskName()) 956 | this.errorNotifyChild(TASK_STATUS_ERROR) 957 | done <- SIGNAL_TASK_FAIL_WAIT_NODE 958 | return 959 | } 960 | 961 | if nil != this.worker { 962 | success := false 963 | if this.execute.printExecuteStruct == true { 964 | this.isPrintDone = true 965 | success = true 966 | } else { 967 | success = this.worker.Execute(this) 968 | } 969 | 970 | if !success { 971 | //fmt.Println("failself:", this.GetTaskName()) 972 | this.execute.logWarn("failself:", this.GetTaskName()) 973 | this.errorNotifyChild(TASK_STATUS_TIMEOUT) 974 | //this.taskType 975 | done <- SIGNAL_TASK_FAIL 976 | return 977 | } 978 | } 979 | 980 | done <- SIGNAL_TASK_DONE 981 | 982 | } 983 | 984 | func (node *TaskNode) NotifyAll() { 985 | size := len(node.notifyList) 986 | for i := 0; i < size; i++ { 987 | notifyNode := node.notifyList[i] 988 | //当waitnumer==0即进入可执行状态 989 | notifyNode.AddWaitNumber(-1) 990 | 991 | //如果执行器超时,则停止触发未完成的任务 992 | if nil != node.execute && (node.execute.isTimeOut == true || node.execute.isCancel == true) { 993 | //fmt.Println("executer timeout can not notify") 994 | node.execute.logWarn("executer timeout can not notify") 995 | //if final node not run,run 996 | if node.execute.finalNode.status == TASK_STATUS_INTI { 997 | if node.isRunInPool() { 998 | node.execute.pool.Submit(func() { 999 | node.execute.finalNode.ExecuteGraph() 1000 | }) 1001 | } else { 1002 | go node.execute.finalNode.ExecuteGraph() 1003 | } 1004 | 1005 | } 1006 | return 1007 | } 1008 | 1009 | if node.isTimeOut == true || (node.isError == true && node.taskType == TASK_TYPE_FAIL_CORE_FAIL) { 1010 | //fmt.Println("task timeout or fail can not notify") 1011 | node.execute.logWarn("task timeout or fail can not notify") 1012 | //if final node not run,run 1013 | node.execute.isCancel = true 1014 | if node.execute.finalNode.status == TASK_STATUS_INTI { 1015 | if node.isRunInPool() { 1016 | node.execute.pool.Submit(func() { 1017 | node.execute.finalNode.ExecuteGraph() 1018 | }) 1019 | } else { 1020 | go node.execute.finalNode.ExecuteGraph() 1021 | } 1022 | } 1023 | return 1024 | } 1025 | 1026 | if notifyNode.waitNumber == 0 { 1027 | if node.isRunInPool() { 1028 | node.execute.pool.Submit(func() { 1029 | notifyNode.ExecuteGraph() 1030 | }) 1031 | } else { 1032 | go notifyNode.ExecuteGraph() 1033 | } 1034 | } 1035 | } 1036 | } 1037 | 1038 | /* 1039 | * 1040 | 1041 | 设置节点失败时,通知子节点不执行 1042 | */ 1043 | func (this *TaskNode) taskTypeFailNotifyChildCancel() { 1044 | this.taskType = TASK_TYPE_FAIL_NOTIFY_CHILD_CANCEL 1045 | } 1046 | 1047 | /* 1048 | * 1049 | 1050 | 设置节点失败时,整体执行器失败 1051 | */ 1052 | func (this *TaskNode) taskTypeFailCoreFail() { 1053 | this.taskType = TASK_TYPE_FAIL_CORE_FAIL 1054 | } 1055 | 1056 | /* 1057 | * 1058 | 1059 | 任务失败或超时,通知子节点 1060 | */ 1061 | func (this *TaskNode) errorNotifyChild(status int32) { 1062 | this.status = status 1063 | if this.taskType >= TASK_TYPE_FAIL_NOTIFY_CHILD_CANCEL { 1064 | if nil != this.notifyList && len(this.notifyList) > 0 { 1065 | for _, task := range this.notifyList { 1066 | if task.GetTaskName() != FINAL_NODE { 1067 | task.status = TASK_STATUS_WAIT_NODE_FAIL 1068 | } 1069 | } 1070 | } 1071 | } 1072 | 1073 | } 1074 | 1075 | func (node *TaskNode) GetTaskName() string { 1076 | return node.name 1077 | } 1078 | 1079 | func (node *TaskNode) HasWaitDepend(delta int32) { 1080 | } 1081 | 1082 | /**添加依赖的任务数 1083 | */ 1084 | func (node *TaskNode) AddWaitNumber(delta int32) { 1085 | 1086 | atomic.AddInt32(&node.waitNumber, delta) 1087 | } 1088 | 1089 | func (node *TaskNode) GetWaitMap() map[string]*TaskNode { 1090 | return node.waitMap 1091 | } 1092 | 1093 | func (node *TaskNode) GetExecuteTime() int64 { 1094 | return node.executeTime 1095 | } 1096 | 1097 | func (node *TaskNode) GetErrorMsg() string { 1098 | return node.errmsg 1099 | } 1100 | 1101 | func (node *TaskNode) GetWaitNode(taskName string) *TaskNode { 1102 | return node.waitMap[taskName] 1103 | } 1104 | 1105 | func (node *TaskNode) GetResutlt(taskName string) interface{} { 1106 | task := node.waitMap[taskName] 1107 | if nil != task && nil != task.worker { 1108 | return task.worker.GetResult() 1109 | } 1110 | 1111 | return nil 1112 | } 1113 | 1114 | func (node *TaskNode) SetTimeout(timeOut int64) { 1115 | node.timeOut = timeOut 1116 | } 1117 | 1118 | func (node *TaskNode) GetWaitNumber() int32 { 1119 | return node.waitNumber 1120 | } 1121 | 1122 | func (node *TaskNode) AddNotifyNumber(delta int32) { 1123 | /*for{ 1124 | v:=atomic.LoadInt32(&node.notifyNumber) 1125 | if atomic.CompareAndSwapInt32(&v,node.notifyNumber,(delta+v)){ 1126 | break 1127 | } 1128 | }*/ 1129 | atomic.AddInt32(&node.notifyNumber, delta) 1130 | } 1131 | 1132 | // 依赖多个任务 1133 | func (node *TaskNode) TaskDependGroup(tasks ...string) error { 1134 | if nil == tasks { 1135 | return CreateError(ERROR_NO_NULL_DEPEND, ERROR_MSG_NULL_DEPEND) 1136 | } 1137 | 1138 | var err error 1139 | for _, taskName := range tasks { 1140 | task := node.execute.taskMap[taskName] 1141 | if nil == task { 1142 | return CreateError(ERROR_NO_NULL_DEPEND, ERROR_MSG_NULL_DEPEND) 1143 | } 1144 | err = node.TaskDepend(task) 1145 | } 1146 | 1147 | return err 1148 | } 1149 | 1150 | func (node *TaskNode) TaskDependName(name string) error { 1151 | task := node.execute.taskMap[name] 1152 | if nil == task { 1153 | return CreateError(ERROR_NO_NULL_DEPEND, ERROR_MSG_NULL_DEPEND) 1154 | } 1155 | 1156 | return node.TaskDepend(task) 1157 | } 1158 | 1159 | func (node *TaskNode) TaskDepend(waitTask *TaskNode) error { 1160 | if nil == waitTask { 1161 | return CreateError(ERROR_NO_NULL_DEPEND, ERROR_MSG_NULL_DEPEND) 1162 | } 1163 | 1164 | if node == waitTask { 1165 | return CreateError(ERROR_NO_SELF_DEPEND, ERROR_MSG_SELF_DEPEND) 1166 | } 1167 | 1168 | //是否依赖过, 1169 | if _, ok := node.waitMap[waitTask.name]; !ok { 1170 | node.waitMap[waitTask.name] = waitTask 1171 | node.waitList = append(node.waitList, waitTask) 1172 | node.AddWaitNumber(1) 1173 | //只有被等待的节点>default时,才赋值到子节点,避免子节点设置的失败级别失效 1174 | if waitTask.taskType >= TASK_TYPE_FAIL_NOTIFY_CHILD_CANCEL { 1175 | node.taskType = waitTask.taskType //task 类型具有传导性,当父节点失败时逐级通知子节点不要执行 1176 | } 1177 | } 1178 | 1179 | //是否被依赖过, 1180 | if _, ok := waitTask.notifyMap[node.name]; !ok { 1181 | waitTask.notifyMap[node.name] = node.name 1182 | waitTask.notifyList = append(waitTask.notifyList, node) 1183 | waitTask.AddNotifyNumber(1) 1184 | } 1185 | 1186 | return nil 1187 | 1188 | } 1189 | --------------------------------------------------------------------------------