task.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package myth
  2. import (
  3. "container/list"
  4. "context"
  5. "log"
  6. "time"
  7. )
  8. // TaskFunc 任务执行函数
  9. type TaskFunc func(string, time.Time)
  10. // 任务主体
  11. type Task struct {
  12. Seconds int64
  13. l *list.List
  14. }
  15. // Tasker 任务接口
  16. type Tasker interface {
  17. // 任务名称
  18. Name() string
  19. // 执行任务时间间隔(秒)
  20. // 返回值
  21. // = 0 时为指定时间执行的任务
  22. Interval() uint64
  23. // 每天指定时间执行的任务(hour:minute:second 时刻执行)
  24. // 返回值
  25. // hour 小时( -1 时, 每小时定时执行)
  26. // minute 分钟
  27. // second 秒
  28. Timing() (hour, minute, second int)
  29. // 新增任务回调
  30. //AddTask(handle TaskHandle)
  31. // 任务回调
  32. //Task() TaskHandle
  33. // 执行任务(go 执行)
  34. // 参数
  35. // now 当前时间
  36. // hour 当前时间小时
  37. // minute 当前时间分钟
  38. // second 当前时间秒
  39. Do(now time.Time, hour, minute, second int)
  40. }
  41. // NewTask 新任务
  42. func NewTask() *Task {
  43. return &Task{l: list.New()}
  44. }
  45. // Add 加入新任务
  46. func (t *Task) Add(tx Tasker) {
  47. t.l.PushBack(tx)
  48. }
  49. func (t *Task) do(nsec int64) {
  50. var (
  51. interval uint64
  52. hour, minute, second int
  53. )
  54. now := time.Now()
  55. h := now.Hour()
  56. m := now.Minute()
  57. s := now.Second()
  58. t.Seconds++
  59. for e := t.l.Front(); e != nil; e = e.Next() {
  60. v, _ := e.Value.(Tasker)
  61. interval = v.Interval()
  62. if interval > 1 {
  63. if nsec%int64(interval) == 0 {
  64. go v.Do(now, h, m, s)
  65. }
  66. continue
  67. } else if interval == 1 { // 每秒任务
  68. go v.Do(now, h, m, s)
  69. continue
  70. }
  71. hour, minute, second = v.Timing()
  72. if second == s {
  73. if minute == m {
  74. switch hour {
  75. case h:
  76. go v.Do(now, h, m, s)
  77. case -1:
  78. // // 整点任务
  79. go v.Do(now, h, m, s)
  80. }
  81. }
  82. }
  83. }
  84. }
  85. func (t *Task) Start(ctx context.Context) {
  86. defer func() {
  87. if rcv := recover(); rcv != nil {
  88. log.Println("Task recover()", rcv)
  89. }
  90. }()
  91. ts := time.NewTicker(1 * time.Second)
  92. nsecs := int64(0)
  93. for {
  94. select {
  95. case <-ctx.Done():
  96. log.Println("Exit")
  97. return
  98. case <-ts.C:
  99. t.do(nsecs)
  100. nsecs++
  101. }
  102. }
  103. }
  104. // ***************** TaskElement begin *****************
  105. // TaskElement 任务
  106. type TaskElement struct {
  107. TaskName string
  108. TimeInterval uint64
  109. Hour int
  110. Minute int
  111. Second int
  112. // N int64
  113. Handle TaskFunc
  114. }
  115. func (t TaskElement) Name() string {
  116. return t.TaskName
  117. }
  118. func (t TaskElement) Interval() uint64 {
  119. return t.TimeInterval
  120. }
  121. func (t TaskElement) Timing() (hour, minute, second int) {
  122. return t.Hour, t.Minute, t.Second
  123. }
  124. func (t *TaskElement) AddTask(handle TaskFunc) {
  125. t.Handle = handle
  126. }
  127. func (t *TaskElement) TaskHandle() TaskFunc {
  128. return t.Handle
  129. }
  130. func (t *TaskElement) Do(now time.Time, hour, minute, second int) {
  131. t.Handle(t.TaskName, now)
  132. }
  133. // ***************** TaskElement end *****************
  134. // NewSecondTasker new
  135. func NewSecondTask(name string, secs uint64, handle TaskFunc) *TaskElement {
  136. return &TaskElement{TaskName: name, Handle: handle, TimeInterval: secs}
  137. }
  138. // NewSecondTask new
  139. func NewMinuteTask(name string, mins uint64, handle TaskFunc) *TaskElement {
  140. return &TaskElement{TaskName: name, Handle: handle, TimeInterval: 60 * mins}
  141. }
  142. // NewHourTask new
  143. func NewHourTask(name string, handle TaskFunc) *TaskElement {
  144. return &TaskElement{TaskName: name, Handle: handle, Hour: -1, Minute: 0, Second: 0}
  145. }
  146. // NewSecondTasker new
  147. func NewDailyTask(name string, hour, minute, second int, handle TaskFunc) *TaskElement {
  148. return &TaskElement{TaskName: name, Handle: handle, Hour: hour, Minute: minute, Second: second, TimeInterval: 0}
  149. }