158 lines
3.3 KiB
Go
158 lines
3.3 KiB
Go
package tasksch
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
TaskStatusBegin = 0
|
|
TaskStatusWorking = 0
|
|
TaskStatusCanceling = 1
|
|
|
|
TaskStatusEndBegin = 2
|
|
TaskStatusFinished = 2
|
|
TaskStatusCanceled = 3
|
|
TaskStatusFailed = 4
|
|
TaskStatusEnd = 4
|
|
)
|
|
|
|
type ITask interface {
|
|
Run() *ITask
|
|
GetResult(duration time.Duration) (retVal []interface{}, err error)
|
|
Cancel()
|
|
GetTotalItemCount() int
|
|
GetFinishedItemCount() int
|
|
GetTotalJobCount() int
|
|
GetFinishedJobCount() int
|
|
GetStatus() int
|
|
}
|
|
|
|
type BaseTask struct {
|
|
Name string `json:"name"`
|
|
ID string `json:"id"`
|
|
ParallelCount int `json:"parallelCount"`
|
|
BatchSize int `json:"batchSize"`
|
|
IsContinueWhenError bool `json:"isContinueWhenError"`
|
|
CreatedBy string `json:"createdBy"`
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
UpdatedAt time.Time `json:"updatedAt"`
|
|
TerminatedAt time.Time `json:"terminatedAt"`
|
|
TotalItemCount int `json:"totalItemCount"`
|
|
TotalJobCount int `json:"totalJobCount"`
|
|
FinishedItemCount int `json:"finishedItemCount"`
|
|
FinishedJobCount int `json:"finishedJobCount"`
|
|
FailedItemCount int `json:"failedItemCount"`
|
|
FailedJobCount int `json:"failedJobCount"`
|
|
Status int `json:"status"`
|
|
|
|
finishChan chan int
|
|
C <-chan int `json:"-"`
|
|
params []interface{}
|
|
quitChan chan int
|
|
|
|
locker sync.RWMutex
|
|
result interface{}
|
|
err error
|
|
}
|
|
|
|
type TaskList []*Task
|
|
|
|
func (s TaskList) Len() int {
|
|
return len(s)
|
|
}
|
|
|
|
func (s TaskList) Less(i, j int) bool {
|
|
return s[i].CreatedAt.Sub(s[j].CreatedAt) < 0
|
|
}
|
|
|
|
func (s TaskList) Swap(i, j int) {
|
|
tmp := s[i]
|
|
s[i] = s[j]
|
|
s[j] = tmp
|
|
}
|
|
|
|
func (t *BaseTask) GetResult(duration time.Duration) (retVal []interface{}, err error) {
|
|
if t.GetStatus() >= TaskStatusEndBegin {
|
|
retVal, _ = t.result.([]interface{})
|
|
return retVal, t.err
|
|
}
|
|
if duration == 0 {
|
|
duration = time.Hour * 10000 // duration为0表示无限等待
|
|
}
|
|
timer := time.NewTimer(duration)
|
|
select {
|
|
case <-t.finishChan:
|
|
timer.Stop()
|
|
t.locker.RLock()
|
|
defer t.locker.RUnlock()
|
|
|
|
retVal, _ = t.result.([]interface{})
|
|
return retVal, t.err
|
|
case <-timer.C:
|
|
}
|
|
return nil, ErrTaskNotFinished
|
|
}
|
|
|
|
func (t *BaseTask) Cancel() {
|
|
t.locker.Lock()
|
|
defer t.locker.Unlock()
|
|
if t.Status < TaskStatusEndBegin && t.Status != TaskStatusCanceling {
|
|
t.Status = TaskStatusCanceling
|
|
for i := 0; i < t.ParallelCount; i++ {
|
|
t.quitChan <- 0
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *BaseTask) GetTotalItemCount() int {
|
|
return t.TotalItemCount
|
|
}
|
|
|
|
func (t *BaseTask) GetFinishedItemCount() int {
|
|
t.locker.RLock()
|
|
defer t.locker.RUnlock()
|
|
|
|
return t.FinishedItemCount
|
|
}
|
|
|
|
func (t *BaseTask) GetTotalJobCount() int {
|
|
return t.TotalJobCount
|
|
}
|
|
|
|
func (t *BaseTask) GetFinishedJobCount() int {
|
|
t.locker.RLock()
|
|
defer t.locker.RUnlock()
|
|
|
|
return t.FinishedJobCount
|
|
}
|
|
|
|
func (t *BaseTask) GetStatus() int {
|
|
t.locker.RLock()
|
|
defer t.locker.RUnlock()
|
|
|
|
return t.Status
|
|
}
|
|
|
|
/////////
|
|
func (t *BaseTask) finishedOneJob(itemCount int, err error) {
|
|
t.locker.Lock()
|
|
defer t.locker.Unlock()
|
|
|
|
t.UpdatedAt = time.Now()
|
|
if err == nil {
|
|
t.FinishedItemCount += itemCount
|
|
t.FinishedJobCount++
|
|
} else {
|
|
t.FailedItemCount += itemCount
|
|
t.FailedJobCount++
|
|
}
|
|
}
|
|
|
|
func (t *BaseTask) setStatus(status int) {
|
|
t.locker.Lock()
|
|
defer t.locker.Unlock()
|
|
|
|
t.Status = status
|
|
}
|