mirror of
https://github.com/Fishwaldo/sched.git
synced 2025-03-15 19:41:46 +00:00
124 lines
2.4 KiB
Go
124 lines
2.4 KiB
Go
package job
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
//Job Wraps JobFun and provide:
|
|
// 1. Creation, Start, and Finish Time
|
|
// 2. Recover From Panics
|
|
type Job struct {
|
|
id string
|
|
jobFunc func()
|
|
createTime time.Time
|
|
startTime time.Time
|
|
finishTime time.Time
|
|
state State
|
|
mx sync.RWMutex
|
|
}
|
|
|
|
//State Return Job current state.
|
|
func (j *Job) State() State {
|
|
j.mx.RLock()
|
|
defer j.mx.RUnlock()
|
|
return j.state
|
|
}
|
|
|
|
//NewJobWithID Create new Job with the supplied Id.
|
|
func NewJobWithID(id string, jobFunc func()) *Job {
|
|
return &Job{
|
|
id: id,
|
|
jobFunc: jobFunc,
|
|
createTime: time.Now(),
|
|
startTime: time.Time{},
|
|
finishTime: time.Time{},
|
|
state: NEW,
|
|
}
|
|
}
|
|
|
|
//NewJob Create new Job, id is assigned a UUID instead.
|
|
func NewJob(jobFunc func()) *Job {
|
|
return NewJobWithID(uuid.New().String(), jobFunc)
|
|
}
|
|
|
|
//ID Return Job ID
|
|
func (j *Job) ID() string {
|
|
return j.id
|
|
}
|
|
|
|
//ActualElapsed Return the actual time of procession of Job.
|
|
// Return -1 if job hasn't started yet.
|
|
func (j *Job) ActualElapsed() time.Duration {
|
|
j.mx.RLock()
|
|
defer j.mx.RUnlock()
|
|
|
|
if !j.startTime.IsZero() {
|
|
if j.finishTime.IsZero() {
|
|
return time.Since(j.startTime)
|
|
}
|
|
return j.finishTime.Sub(j.startTime)
|
|
}
|
|
return -1
|
|
}
|
|
|
|
//TotalElapsed Returns the total time between creation of object and finishing processing its job.
|
|
// Return -1 if job hasn't started yet.
|
|
func (j *Job) TotalElapsed() time.Duration {
|
|
j.mx.RLock()
|
|
defer j.mx.RUnlock()
|
|
|
|
if !j.startTime.IsZero() {
|
|
if j.finishTime.IsZero() {
|
|
return time.Since(j.createTime)
|
|
}
|
|
return j.finishTime.Sub(j.createTime)
|
|
}
|
|
return -1
|
|
}
|
|
|
|
//Run Run the internal Job (synchronous)
|
|
func (j *Job) Run() error {
|
|
return j.run()
|
|
}
|
|
|
|
func (j *Job) run() (err error) {
|
|
j.mx.Lock()
|
|
if j.state != NEW {
|
|
if j.state == RUNNING {
|
|
err = ErrorJobStarted{Message: "job already started"}
|
|
} else {
|
|
err = ErrorJobStarted{Message: "job finished execution"}
|
|
}
|
|
j.mx.Unlock()
|
|
return err
|
|
}
|
|
|
|
// Handle Panics and set correct state
|
|
defer func() {
|
|
j.mx.Lock()
|
|
// TODO handle panics
|
|
if r := recover(); r != nil {
|
|
err = ErrorJobPanic{Message: fmt.Sprintf("job panicked: %v", r)}
|
|
j.state = PANICKED
|
|
} else {
|
|
j.state = FINISHED
|
|
}
|
|
j.finishTime = time.Now()
|
|
j.mx.Unlock()
|
|
}()
|
|
|
|
j.state = RUNNING
|
|
j.startTime = time.Now()
|
|
|
|
// Unlock State
|
|
j.mx.Unlock()
|
|
|
|
// Run Job
|
|
j.jobFunc()
|
|
|
|
return nil
|
|
}
|