forked from wechatpay-apiv3/wechatpay-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
repeated_task.go
111 lines (91 loc) · 2.34 KB
/
repeated_task.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright 2021 Tencent Inc. All rights reserved.
package task
import (
"runtime"
"sync"
"time"
)
// State RepeatedTask 状态类型
type State int
// State 可能枚举
const (
Init State = iota
Running
Stopped
)
// implRepeatedTask 定时重复任务
// 将会在后台(另一个goroutine中)定时重复执行给定的任务
//
// 注意:
// 1. 请不要在多个协程中操作同一个 implRepeatedTask 实例,它并不支持多协程并发
// 2. 基于上一条,请不要在 handler 中操作本 implRepeatedTask 实例
type implRepeatedTask struct {
interval time.Duration
handler func(time.Time)
state State
ticker *time.Ticker
closed chan struct{}
wg sync.WaitGroup
}
// State 查看当前任务状态
func (t *implRepeatedTask) State() State {
return t.state
}
// Interval 查看当前任务间隔
func (t *implRepeatedTask) Interval() time.Duration {
return t.interval
}
// Start 启动重复任务
// 当且仅当任务并未启动时有效,其他状态下不会发生任何事
func (t *implRepeatedTask) Start() {
if t.state != Init {
return
}
t.ticker = time.NewTicker(t.interval)
t.wg.Add(1)
go func() {
defer t.wg.Done()
t.run()
}()
t.state = Running
}
// Stop 停止重复任务
// 当且仅当任务处于 Running 状态时有效,其他状态下不会发生任何事
func (t *implRepeatedTask) Stop() {
if t.state != Running {
return
}
close(t.closed)
t.wg.Wait()
t.ticker.Stop()
t.state = Stopped
}
func (t *implRepeatedTask) run() {
for {
select {
case <-t.closed:
return
case tickTime := <-t.ticker.C:
t.handler(tickTime)
}
}
}
type wrapper struct {
*implRepeatedTask
}
// RepeatedTask 自动重复任务
// 设定间隔时间与任务Handler即可自动按间隔执行,在你不再持有该实例的引用后,任务自动停止。
// 也可以调用 Stop 方法来停止任务
type RepeatedTask wrapper
// NewRepeatedTask 初始化一个自动重复任务
// 创建成功后请调用 Start 方法启动任务,启动后需等待 interval 时间发生第一次调用
func NewRepeatedTask(interval time.Duration, handler func(time.Time)) *RepeatedTask {
task := implRepeatedTask{
closed: make(chan struct{}),
interval: interval,
handler: handler,
}
result := &RepeatedTask{&task}
runtime.SetFinalizer(result, func(t *RepeatedTask) { t.Stop() })
return result
}