89 lines
1.4 KiB
Go
89 lines
1.4 KiB
Go
package crontab
|
|
|
|
import (
|
|
"container/heap"
|
|
"errors"
|
|
"jiacrontab/pkg/pqueue"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Task 任务
|
|
type Task = pqueue.Item
|
|
|
|
type Crontab struct {
|
|
pq pqueue.PriorityQueue
|
|
mux sync.RWMutex
|
|
ready chan *Task
|
|
}
|
|
|
|
func New() *Crontab {
|
|
return &Crontab{
|
|
pq: pqueue.New(10000),
|
|
ready: make(chan *Task, 10000),
|
|
}
|
|
}
|
|
|
|
// AddJob 添加未经处理的job
|
|
func (c *Crontab) AddJob(j *Job) error {
|
|
nt, err := j.NextExecutionTime(time.Now())
|
|
if err != nil {
|
|
return errors.New("Invalid execution time")
|
|
}
|
|
c.mux.Lock()
|
|
heap.Push(&c.pq, &Task{
|
|
Priority: nt.UnixNano(),
|
|
Value: j,
|
|
})
|
|
c.mux.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// AddJob 添加延时任务
|
|
func (c *Crontab) AddTask(t *Task) {
|
|
c.mux.Lock()
|
|
heap.Push(&c.pq, t)
|
|
c.mux.Unlock()
|
|
}
|
|
|
|
func (c *Crontab) Len() int {
|
|
c.mux.RLock()
|
|
len := len(c.pq)
|
|
c.mux.RUnlock()
|
|
return len
|
|
}
|
|
|
|
func (c *Crontab) GetAllTask() []*Task {
|
|
c.mux.Lock()
|
|
list := c.pq
|
|
c.mux.Unlock()
|
|
return list
|
|
}
|
|
|
|
func (c *Crontab) Ready() <-chan *Task {
|
|
return c.ready
|
|
}
|
|
|
|
func (c *Crontab) QueueScanWorker() {
|
|
refreshTicker := time.NewTicker(20 * time.Millisecond)
|
|
for {
|
|
select {
|
|
case <-refreshTicker.C:
|
|
if len(c.pq) == 0 {
|
|
continue
|
|
}
|
|
start:
|
|
c.mux.Lock()
|
|
now := time.Now().UnixNano()
|
|
job, _ := c.pq.PeekAndShift(now)
|
|
c.mux.Unlock()
|
|
if job == nil {
|
|
continue
|
|
}
|
|
c.ready <- job
|
|
goto start
|
|
|
|
}
|
|
}
|
|
}
|