task.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package myth
  2. import (
  3. "container/list"
  4. "context"
  5. "log"
  6. "time"
  7. )
  8. // TaskFunc 任务执行函数
  9. type TaskFunc func(ctx context.Context, name string, now 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(ctx context.Context, 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(ctx context.Context, 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(ctx, now, h, m, s)
  65. }
  66. continue
  67. } else if interval == 1 { // 每秒任务
  68. go v.Do(ctx, now, h, m, s)
  69. continue
  70. }
  71. // 小时、天任务
  72. hour, minute, second = v.Timing()
  73. if second == s {
  74. if minute == m {
  75. switch hour {
  76. case h:
  77. // 指定 时、分、秒 任务(每天)
  78. go v.Do(ctx, now, h, m, s)
  79. case -1:
  80. // 整点(小时)任务
  81. go v.Do(ctx, now, h, m, s)
  82. }
  83. }
  84. }
  85. }
  86. }
  87. func (t *Task) Start(ctx context.Context) {
  88. defer func() {
  89. if rcv := recover(); rcv != nil {
  90. log.Println("Task recover()", rcv)
  91. }
  92. }()
  93. ts := time.NewTicker(1 * time.Second)
  94. nsecs := int64(0)
  95. for {
  96. select {
  97. case <-ctx.Done():
  98. log.Println("Task Exit", ctx.Err())
  99. ts.Stop()
  100. return
  101. case <-ts.C:
  102. t.do(ctx, nsecs)
  103. nsecs++
  104. }
  105. }
  106. }
  107. // ***************** TaskElement begin *****************
  108. // TaskElement 任务
  109. type TaskElement struct {
  110. // 任务名称
  111. TaskName string
  112. // 任务执行间隔时间(秒)
  113. // > 1 超 1 秒
  114. // = 1 每秒
  115. // = 0 每天、小时任务(时、分、秒 需要有效指定)
  116. // < 1 指定时间
  117. TimeInterval uint64
  118. // -1 整点任务 (TimeInterval < 1)
  119. // >= 0 指定执行小时时间(0-23 有效, TimeInterval = 0)
  120. Hour int
  121. // 指定执行分钟时间(0-60 有效)
  122. Minute int
  123. // 指定执行秒时间(0-60 有效)
  124. Second int
  125. // N int64
  126. Handle TaskFunc
  127. }
  128. func (t TaskElement) Name() string {
  129. return t.TaskName
  130. }
  131. func (t TaskElement) Interval() uint64 {
  132. return t.TimeInterval
  133. }
  134. func (t TaskElement) Timing() (hour, minute, second int) {
  135. return t.Hour, t.Minute, t.Second
  136. }
  137. func (t *TaskElement) AddTask(handle TaskFunc) {
  138. t.Handle = handle
  139. }
  140. func (t *TaskElement) TaskHandle() TaskFunc {
  141. return t.Handle
  142. }
  143. func (t *TaskElement) Do(ctx context.Context, now time.Time, hour, minute, second int) {
  144. t.Handle(ctx, t.TaskName, now)
  145. }
  146. // ***************** TaskElement end *****************
  147. // NewSecondTasker new
  148. func NewSecondTask(name string, secs uint64, handle TaskFunc) *TaskElement {
  149. return &TaskElement{TaskName: name, Handle: handle, TimeInterval: secs}
  150. }
  151. // NewSecondTask new
  152. func NewMinuteTask(name string, mins uint64, handle TaskFunc) *TaskElement {
  153. return &TaskElement{TaskName: name, Handle: handle, TimeInterval: 60 * mins}
  154. }
  155. // NewHourTask new
  156. func NewHourTask(name string, handle TaskFunc) *TaskElement {
  157. return &TaskElement{TaskName: name, Handle: handle, Hour: -1, Minute: 0, Second: 0}
  158. }
  159. // NewSecondTasker new
  160. func NewDailyTask(name string, hour, minute, second int, handle TaskFunc) *TaskElement {
  161. return &TaskElement{TaskName: name, Handle: handle, Hour: hour, Minute: minute, Second: second, TimeInterval: 0}
  162. }