rework locker + fix job state + fix graceful stop
This commit is contained in:
parent
4da553d156
commit
0cd4f264a3
@ -59,7 +59,6 @@ type JobDetails struct {
|
|||||||
Err string `json:"error"`
|
Err string `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(rmanach): add priority level
|
|
||||||
type Job struct {
|
type Job struct {
|
||||||
l sync.RWMutex
|
l sync.RWMutex
|
||||||
id uuid.UUID
|
id uuid.UUID
|
||||||
@ -130,7 +129,10 @@ func (j *Job) setFail(err error) {
|
|||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
j.updatedAt = &now
|
j.updatedAt = &now
|
||||||
|
|
||||||
|
if j.state != Abort {
|
||||||
j.state = Failed
|
j.state = Failed
|
||||||
|
}
|
||||||
|
|
||||||
j.err = err
|
j.err = err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,18 +29,42 @@ const (
|
|||||||
High
|
High
|
||||||
)
|
)
|
||||||
|
|
||||||
type jobSlot struct {
|
type JobSlotDetails struct {
|
||||||
*job.Job
|
job.JobDetails
|
||||||
row int
|
Attempts int `json:"attempts"`
|
||||||
col int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newJobSlot(task job.FnJob, row, col int) jobSlot {
|
type jobSlot struct {
|
||||||
j := job.NewJob(task)
|
l sync.RWMutex
|
||||||
|
job.Job
|
||||||
|
slot int
|
||||||
|
attempts int
|
||||||
|
// priority Priority
|
||||||
|
}
|
||||||
|
|
||||||
|
func newJobSlot(task job.FnJob, slot int) jobSlot {
|
||||||
return jobSlot{
|
return jobSlot{
|
||||||
Job: &j,
|
Job: job.NewJob(task),
|
||||||
row: row,
|
slot: slot,
|
||||||
col: col,
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *jobSlot) run(ctx context.Context) {
|
||||||
|
j.l.Lock()
|
||||||
|
defer j.l.Unlock()
|
||||||
|
|
||||||
|
j.attempts += 1
|
||||||
|
|
||||||
|
j.Job.Run(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *jobSlot) getDetails() JobSlotDetails {
|
||||||
|
j.l.RLock()
|
||||||
|
defer j.l.RUnlock()
|
||||||
|
|
||||||
|
return JobSlotDetails{
|
||||||
|
JobDetails: j.IntoDetails(),
|
||||||
|
Attempts: j.attempts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,22 +119,22 @@ func (c *SchedulerCycle) Done() <-chan struct{} {
|
|||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
<-c.ctx.Done()
|
<-c.ctx.Done()
|
||||||
c.wg.Done()
|
c.wg.Wait()
|
||||||
done <- struct{}{}
|
done <- struct{}{}
|
||||||
}()
|
}()
|
||||||
return done
|
return done
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SchedulerCycle) Len() int {
|
func (c *SchedulerCycle) Len() int {
|
||||||
c.l.Lock()
|
c.l.RLock()
|
||||||
defer c.l.Unlock()
|
defer c.l.RUnlock()
|
||||||
|
|
||||||
return len(c.jobs)
|
return len(c.jobs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SchedulerCycle) HasAllJobsDone() bool {
|
func (c *SchedulerCycle) HasAllJobsDone() bool {
|
||||||
c.l.Lock()
|
c.l.RLock()
|
||||||
defer c.l.Unlock()
|
defer c.l.RUnlock()
|
||||||
|
|
||||||
for _, j := range c.jobs {
|
for _, j := range c.jobs {
|
||||||
if j.GetState() == job.Pending || j.GetState() == job.Running {
|
if j.GetState() == job.Pending || j.GetState() == job.Running {
|
||||||
@ -121,13 +145,13 @@ func (c *SchedulerCycle) HasAllJobsDone() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SchedulerCycle) GetJobsDetails() []job.JobDetails {
|
func (c *SchedulerCycle) GetJobsDetails() []JobSlotDetails {
|
||||||
c.l.Lock()
|
c.l.RLock()
|
||||||
defer c.l.Unlock()
|
defer c.l.RUnlock()
|
||||||
|
|
||||||
details := []job.JobDetails{}
|
details := []JobSlotDetails{}
|
||||||
for _, j := range c.jobs {
|
for _, j := range c.jobs {
|
||||||
details = append(details, j.IntoDetails())
|
details = append(details, j.getDetails())
|
||||||
}
|
}
|
||||||
|
|
||||||
return details
|
return details
|
||||||
@ -135,6 +159,12 @@ func (c *SchedulerCycle) GetJobsDetails() []job.JobDetails {
|
|||||||
|
|
||||||
// Delay builds a job and add it to the scheduler engine.
|
// Delay builds a job and add it to the scheduler engine.
|
||||||
func (c *SchedulerCycle) Delay(fnJob job.FnJob) uuid.UUID {
|
func (c *SchedulerCycle) Delay(fnJob job.FnJob) uuid.UUID {
|
||||||
|
select {
|
||||||
|
case <-c.Done():
|
||||||
|
log.Error().Msg("context done unable to add new job")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
c.l.Lock()
|
c.l.Lock()
|
||||||
defer c.l.Unlock()
|
defer c.l.Unlock()
|
||||||
|
|
||||||
@ -143,7 +173,7 @@ func (c *SchedulerCycle) Delay(fnJob job.FnJob) uuid.UUID {
|
|||||||
nextSlot = 0
|
nextSlot = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
j := newJobSlot(fnJob, nextSlot, len(c.slots[nextSlot]))
|
j := newJobSlot(fnJob, nextSlot)
|
||||||
|
|
||||||
c.slots[nextSlot] = append(c.slots[nextSlot], &j)
|
c.slots[nextSlot] = append(c.slots[nextSlot], &j)
|
||||||
c.jobs[j.GetID()] = &j
|
c.jobs[j.GetID()] = &j
|
||||||
@ -165,18 +195,20 @@ func (c *SchedulerCycle) Abort(id uuid.UUID) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetJobDetails returns the job details by .
|
// GetJobDetails returns the job details by .
|
||||||
func (c *SchedulerCycle) GetJobDetails(id uuid.UUID) job.JobDetails {
|
func (c *SchedulerCycle) GetJobDetails(id uuid.UUID) JobSlotDetails {
|
||||||
c.l.Lock()
|
c.l.RLock()
|
||||||
defer c.l.Unlock()
|
defer c.l.RUnlock()
|
||||||
|
|
||||||
j, ok := c.jobs[id]
|
j, ok := c.jobs[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return job.JobDetails{
|
return JobSlotDetails{
|
||||||
State: job.Unknown.String(),
|
JobDetails: job.JobDetails{
|
||||||
|
State: job.UnknownState,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return j.IntoDetails()
|
return j.getDetails()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display outputs earch interval the scheduler state.
|
// Display outputs earch interval the scheduler state.
|
||||||
@ -285,11 +317,11 @@ func (c *SchedulerCycle) getCurrentSlotJobs() (int, []*jobSlot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// updateSlot add a job to the slot where it was before.
|
// updateSlot add a job to the slot where it was before.
|
||||||
func (c *SchedulerCycle) updateSlot(row int, j *jobSlot) {
|
func (c *SchedulerCycle) updateSlot(slot int, j *jobSlot) {
|
||||||
c.l.Lock()
|
c.l.Lock()
|
||||||
defer c.l.Unlock()
|
defer c.l.Unlock()
|
||||||
|
|
||||||
c.slots[row] = append(c.slots[row], j)
|
c.slots[slot] = append(c.slots[slot], j)
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateCurrentSlot add a job to the current slot.
|
// updateCurrentSlot add a job to the current slot.
|
||||||
@ -320,7 +352,7 @@ func (c *SchedulerCycle) incr() {
|
|||||||
// It all the workers are busy, the jobs are re-schedule in the same slot
|
// It all the workers are busy, the jobs are re-schedule in the same slot
|
||||||
// to be executed in the next cycle.
|
// to be executed in the next cycle.
|
||||||
func (c *SchedulerCycle) dispatch() {
|
func (c *SchedulerCycle) dispatch() {
|
||||||
row, jobs := c.getCurrentSlotJobs()
|
slot, jobs := c.getCurrentSlotJobs()
|
||||||
for _, j := range jobs {
|
for _, j := range jobs {
|
||||||
if j.GetState() == job.Abort {
|
if j.GetState() == job.Abort {
|
||||||
continue
|
continue
|
||||||
@ -330,7 +362,7 @@ func (c *SchedulerCycle) dispatch() {
|
|||||||
case c.chJobs <- j:
|
case c.chJobs <- j:
|
||||||
default:
|
default:
|
||||||
log.Warn().Msg("unable to put job in workers, trying next cycle")
|
log.Warn().Msg("unable to put job in workers, trying next cycle")
|
||||||
c.updateSlot(row, j)
|
c.updateSlot(slot, j)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,7 +394,7 @@ func (c *SchedulerCycle) workers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *SchedulerCycle) executeJob(j *jobSlot, fnFallBack func(*jobSlot)) {
|
func (c *SchedulerCycle) executeJob(j *jobSlot, fnFallBack func(*jobSlot)) {
|
||||||
j.Run(c.ctx)
|
j.run(c.ctx)
|
||||||
if j.GetState() == job.Pending {
|
if j.GetState() == job.Pending {
|
||||||
fnFallBack(j)
|
fnFallBack(j)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user