github.com/leg100/ots@v0.0.7-0.20210919080622-034055ced4bd/workspace_queue.go (about) 1 package ots 2 3 type PlanEnqueuer interface { 4 EnqueuePlan(id string) error 5 } 6 7 // Queue implementations are able to add and remove runs from a queue-like 8 // structure 9 type Queue interface { 10 Add(*Run) error 11 Remove(*Run) error 12 } 13 14 // WorkspaceQueue is the queue of runs for a workspace. The queue has at most 15 // one active run, which blocks other pending runs. Speculative runs do not 16 // block and are therefore not added to the queue. 17 type WorkspaceQueue struct { 18 // Active is the currently active run. 19 Active *Run 20 // Pending is the list of pending runs waiting for the active run to 21 // complete. 22 Pending []*Run 23 // PlanEnqueuer enqueues a plan onto the global queue 24 PlanEnqueuer 25 } 26 27 // Add adds a run to the workspace queue. 28 func (q *WorkspaceQueue) Add(run *Run) error { 29 // Enqueue speculative runs onto (global) queue but don't make them active 30 // because they do not block pending runs 31 if run.IsSpeculative() { 32 return q.EnqueuePlan(run.ID) 33 } 34 35 // No run is current active, so make this run active 36 if q.Active == nil { 37 if err := q.EnqueuePlan(run.ID); err != nil { 38 return err 39 } 40 41 q.Active = run 42 return nil 43 } 44 45 // Other add run to pending queue 46 q.Pending = append(q.Pending, run) 47 48 return nil 49 } 50 51 // Remove removes a run from the queue. 52 func (q *WorkspaceQueue) Remove(run *Run) error { 53 // Speculative runs are never added to the queue in the first place so they 54 // do not need to be removed 55 if run.IsSpeculative() { 56 return nil 57 } 58 59 // Remove active run and make the first pending run the active run 60 if q.Active.ID == run.ID { 61 q.Active = nil 62 if len(q.Pending) > 0 { 63 if err := q.EnqueuePlan(q.Pending[0].ID); err != nil { 64 return err 65 } 66 67 q.Active = q.Pending[0] 68 q.Pending = q.Pending[1:] 69 } 70 return nil 71 } 72 73 // Remove run from pending queue 74 for idx, p := range q.Pending { 75 if p.ID == run.ID { 76 q.Pending = append(q.Pending[:idx], q.Pending[idx+1:]...) 77 return nil 78 } 79 } 80 81 return nil 82 }