This commit is contained in:
2022-03-17 15:55:27 +08:00
commit bd5a9fad97
92 changed files with 13861 additions and 0 deletions

99
dtask/job.go Normal file
View File

@@ -0,0 +1,99 @@
package dtask
import (
"gitlab.33.cn/chat/im/dtask/pkg/rbtree"
"log"
"runtime/debug"
"sync/atomic"
"time"
)
/*
This code is based on the following resources:
source code: https://github.com/alex023/clock.git
*/
// Job External access interface for timed tasks
type Job interface {
C() <-chan Job //C Get a Chanwhich can get message if Job is executed
Count() uint64 //计数器,表示已执行(或触发)的次数
Max() uint64 //允许执行的最大次数
Cancel() //撤销加载的任务,不再定时执行
isAvailable() bool //return trueif job not action or not cancel
}
// jobItem implementation of "Job" interface and "rbtree.Item" interface
type jobItem struct {
id uint64 //唯一键值,内部由管理器生成,以区分同一时刻的不同任务事件
actionCount uint64 //计数器,表示已执行(或触发)的次数
actionMax uint64 //允许执行的最大次数
intervalTime time.Duration //间隔时间
createTime time.Time //创建时间,略有误差
actionTime time.Time //计算得出的最近一次执行时间点
fn func() //事件函数
msgChan chan Job //消息通道,执行时,控制器通过该通道向外部传递消息
cancelFlag int32
clock *Clock
}
// Less Based rbtree implements Item interface for sort
func (je jobItem) Less(another rbtree.Item) bool {
item, ok := another.(*jobItem)
if !ok {
return false
}
if !je.actionTime.Equal(item.actionTime) {
return je.actionTime.Before(item.actionTime)
}
return je.id < item.id
}
func (je *jobItem) C() <-chan Job {
return je.msgChan
}
func (je *jobItem) action(async bool) {
je.actionCount++
if async {
go safeCall(je.fn)
} else {
safeCall(je.fn)
}
select {
case je.msgChan <- je:
default:
//some times,client should not receive msgChan,so must discard jobItem when blocking
}
}
func (je *jobItem) Cancel() {
if atomic.CompareAndSwapInt32(&je.cancelFlag, 0, 1) {
je.clock.rmJob(je)
je.innerCancel()
}
}
func (je *jobItem) isAvailable() bool {
return je.cancelFlag == 0
}
func (je *jobItem) innerCancel() {
je.clock = nil
close(je.msgChan)
}
// Count implement for Job
func (je jobItem) Count() uint64 {
return je.actionCount
}
// Max implement for Job
func (je jobItem) Max() uint64 {
return je.actionMax
}
func safeCall(fn func()) {
defer func() {
if err := recover(); err != nil {
log.Printf("[clock] recovering reason is %+v. More detail:", err)
log.Println(string(debug.Stack()))
}
}()
fn()
}