Files
jx-callback/business/jxutils/tasksch/task.go
2018-10-19 18:34:31 +08:00

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
}