From e7bf70c3e001d35721d23e300df68fcebb4276df Mon Sep 17 00:00:00 2001 From: Sherif Abdel-Naby Date: Sat, 3 Apr 2021 06:43:16 +0200 Subject: [PATCH] Job Wrapper / Add RMutex Locks Signed-off-by: Sherif Abdel-Naby --- job/error.go | 14 ++++++------- job/{interface.go => job.go} | 40 +++++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 14 deletions(-) rename job/{interface.go => job.go} (61%) diff --git a/job/error.go b/job/error.go index 77462d8..e6b6814 100644 --- a/job/error.go +++ b/job/error.go @@ -1,17 +1,17 @@ -package Job +package job type ErrorJobPanic struct { - Name string + Message string } func (e ErrorJobPanic) Error() string { - return e.Name + return e.Message } -type ErrorJobNotStarted struct { - Name string +type ErrorJobStarted struct { + Message string } -func (e ErrorJobNotStarted) Error() string { - return e.Name +func (e ErrorJobStarted) Error() string { + return e.Message } diff --git a/job/interface.go b/job/job.go similarity index 61% rename from job/interface.go rename to job/job.go index 9414411..a7325e5 100644 --- a/job/interface.go +++ b/job/job.go @@ -1,12 +1,13 @@ -package Job +package job import ( "fmt" "github.com/google/uuid" + "sync" "time" ) -type State int +type State int64 const ( NEW State = iota @@ -22,6 +23,11 @@ type Job struct { startTime time.Time finishTime time.Time state State + mx sync.RWMutex +} + +func (j *Job) State() State { + return j.state } func NewJobWithID(id string, jobFunc func()) *Job { @@ -43,14 +49,17 @@ func (j *Job) ID() string { 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.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 { @@ -58,20 +67,37 @@ func (j *Job) Start() 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.startTime = time.Now() // Handle Panics and set correct state defer func() { + j.mx.Lock() if r := recover(); r != nil { - err = fmt.Errorf("job panicked: %v", r) + err = ErrorJobPanic{Message: fmt.Sprintf("job panicked: %v", r)} j.state = PANICKED } else { j.state = FINISHED } j.finishTime = time.Now() + j.mx.Unlock() }() + // Unlock State + j.mx.Unlock() + // Start Job j.jobFunc()