Job Wrapper / Add RMutex Locks

Signed-off-by: Sherif Abdel-Naby <sherifabdlnaby@gmail.com>
This commit is contained in:
Sherif Abdel-Naby 2021-04-03 06:43:16 +02:00
parent 095b56b46d
commit e7bf70c3e0
2 changed files with 40 additions and 14 deletions

View file

@ -1,17 +1,17 @@
package Job package job
type ErrorJobPanic struct { type ErrorJobPanic struct {
Name string Message string
} }
func (e ErrorJobPanic) Error() string { func (e ErrorJobPanic) Error() string {
return e.Name return e.Message
} }
type ErrorJobNotStarted struct { type ErrorJobStarted struct {
Name string Message string
} }
func (e ErrorJobNotStarted) Error() string { func (e ErrorJobStarted) Error() string {
return e.Name return e.Message
} }

View file

@ -1,12 +1,13 @@
package Job package job
import ( import (
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
"sync"
"time" "time"
) )
type State int type State int64
const ( const (
NEW State = iota NEW State = iota
@ -22,6 +23,11 @@ type Job struct {
startTime time.Time startTime time.Time
finishTime time.Time finishTime time.Time
state State state State
mx sync.RWMutex
}
func (j *Job) State() State {
return j.state
} }
func NewJobWithID(id string, jobFunc func()) *Job { func NewJobWithID(id string, jobFunc func()) *Job {
@ -43,14 +49,17 @@ func (j *Job) ID() string {
return j.id return j.id
} }
func (j *Job) Duration() (time.Duration, error) { func (j *Job) Duration() time.Duration {
j.mx.RLock()
defer j.mx.RUnlock()
if !j.startTime.IsZero() { if !j.startTime.IsZero() {
if j.finishTime.IsZero() { if j.finishTime.IsZero() {
return time.Since(j.startTime), nil return time.Since(j.startTime)
} }
return j.finishTime.Sub(j.startTime), nil return j.finishTime.Sub(j.startTime)
} }
return -1, fmt.Errorf("job hasn't started yet") return -1
} }
func (j *Job) Start() error { func (j *Job) Start() error {
@ -58,20 +67,37 @@ func (j *Job) Start() error {
} }
func (j *Job) start() (err error) { func (j *Job) start() (err error) {
j.mx.RLock()
if j.state != NEW {
if j.state == STARTED {
err = ErrorJobStarted{Message: "job already started"}
return err
}
err = ErrorJobStarted{Message: "job finished execution"}
return err
}
j.mx.RUnlock()
j.mx.Lock()
j.state = STARTED j.state = STARTED
j.startTime = time.Now() j.startTime = time.Now()
// Handle Panics and set correct state // Handle Panics and set correct state
defer func() { defer func() {
j.mx.Lock()
if r := recover(); r != nil { if r := recover(); r != nil {
err = fmt.Errorf("job panicked: %v", r) err = ErrorJobPanic{Message: fmt.Sprintf("job panicked: %v", r)}
j.state = PANICKED j.state = PANICKED
} else { } else {
j.state = FINISHED j.state = FINISHED
} }
j.finishTime = time.Now() j.finishTime = time.Now()
j.mx.Unlock()
}() }()
// Unlock State
j.mx.Unlock()
// Start Job // Start Job
j.jobFunc() j.jobFunc()