@@ -24,9 +24,18 @@ type logRecord struct {
24
24
time time.Time
25
25
}
26
26
27
- type resourceLock struct {
28
- lock bool
29
- holder * TaskRunner
27
+ type EventType uint
28
+
29
+ const (
30
+ EventTypeNew EventType = 0
31
+ EventTypeFinished EventType = 1
32
+ EventTypeFailed EventType = 2
33
+ EventTypeEmpty EventType = 3
34
+ )
35
+
36
+ type PoolEvent struct {
37
+ eventType EventType
38
+ task * TaskRunner
30
39
}
31
40
32
41
type TaskPool struct {
@@ -47,7 +56,7 @@ type TaskPool struct {
47
56
48
57
store db.Store
49
58
50
- resourceLocker chan * resourceLock
59
+ queueEvents chan PoolEvent
51
60
52
61
aliases map [string ]* TaskRunner
53
62
}
@@ -100,41 +109,10 @@ func (p *TaskPool) Run() {
100
109
ticker := time .NewTicker (5 * time .Second )
101
110
102
111
defer func () {
103
- close (p .resourceLocker )
104
112
ticker .Stop ()
105
113
}()
106
114
107
- // Lock or unlock resources when running a TaskRunner
108
- go func (locker <- chan * resourceLock ) {
109
- for l := range locker {
110
- t := l .holder
111
-
112
- if l .lock {
113
- if p .blocks (t ) {
114
- panic ("Trying to lock an already locked resource!" )
115
- }
116
-
117
- projTasks , ok := p .activeProj [t .Task .ProjectID ]
118
- if ! ok {
119
- projTasks = make (map [int ]* TaskRunner )
120
- p .activeProj [t .Task .ProjectID ] = projTasks
121
- }
122
- projTasks [t .Task .ID ] = t
123
- p .RunningTasks [t .Task .ID ] = t
124
- continue
125
- }
126
-
127
- if p .activeProj [t .Task .ProjectID ] != nil && p .activeProj [t .Task .ProjectID ][t .Task .ID ] != nil {
128
- delete (p .activeProj [t .Task .ProjectID ], t .Task .ID )
129
- if len (p .activeProj [t .Task .ProjectID ]) == 0 {
130
- delete (p .activeProj , t .Task .ProjectID )
131
- }
132
- }
133
-
134
- delete (p .RunningTasks , t .Task .ID )
135
- delete (p .aliases , t .Alias )
136
- }
137
- }(p .resourceLocker )
115
+ go p .handleQueue ()
138
116
139
117
for {
140
118
select {
@@ -153,67 +131,87 @@ func (p *TaskPool) Run() {
153
131
case task := <- p .register : // new task created by API or schedule
154
132
155
133
db .StoreSession (p .store , "new task" , func () {
156
- p .Queue = append (p .Queue , task )
134
+ // p.Queue = append(p.Queue, task)
157
135
log .Debug (task )
158
136
msg := "Task " + strconv .Itoa (task .Task .ID ) + " added to queue"
159
137
task .Log (msg )
160
138
log .Info (msg )
161
139
task .saveStatus ()
162
140
})
141
+ p .queueEvents <- PoolEvent {EventTypeNew , task }
163
142
164
143
case <- ticker .C : // timer 5 seconds
165
- if len (p .Queue ) == 0 {
166
- break
167
- }
144
+ p .queueEvents <- PoolEvent {EventTypeEmpty , nil }
168
145
169
- var t * TaskRunner
146
+ }
147
+ }
148
+ }
170
149
171
- for i := range p .Queue {
172
- curr := p .Queue [i ]
150
+ func (p * TaskPool ) handleQueue () {
151
+ for t := range p .queueEvents {
152
+ switch t .eventType {
153
+ case EventTypeNew :
154
+ p .Queue = append (p .Queue , t .task )
155
+ case EventTypeFinished :
156
+ p .onTaskStop (t .task )
157
+ }
173
158
174
- if curr .Task .Status == task_logger .TaskFailStatus {
175
- //delete failed TaskRunner from queue
176
- p .Queue = slices .Delete (p .Queue , i , i + 1 )
177
- log .Info ("Task " + strconv .Itoa (curr .Task .ID ) + " removed from queue" )
178
- continue
179
- }
159
+ if len (p .Queue ) == 0 {
160
+ continue
161
+ }
180
162
181
- if p . blocks ( curr ) {
182
- continue
183
- }
163
+ var i = 0
164
+ for i < len ( p . Queue ) {
165
+ curr := p . Queue [ i ]
184
166
185
- t = curr
186
- break
167
+ if curr .Task .Status == task_logger .TaskFailStatus {
168
+ //delete failed TaskRunner from queue
169
+ p .Queue = slices .Delete (p .Queue , i , i + 1 )
170
+ log .Info ("Task " + strconv .Itoa (curr .Task .ID ) + " removed from queue" )
171
+ continue
187
172
}
188
173
189
- if t == nil {
190
- break
174
+ if p .blocks (curr ) {
175
+ i = i + 1
176
+ continue
191
177
}
192
178
193
- ////get TaskRunner from top of queue
194
- //t := p.Queue[0]
195
- //if t.Task.Status == task_logger.TaskFailStatus {
196
- // //delete failed TaskRunner from queue
197
- // p.Queue = p.Queue[1:]
198
- // log.Info("Task " + strconv.Itoa(t.Task.ID) + " removed from queue")
199
- // break
200
- //}
201
- //
202
- //if p.blocks(t) {
203
- // //move blocked TaskRunner to end of queue
204
- // //p.Queue = append(p.Queue[1:], t)
205
- // break
206
- //}
207
-
208
- log .Info ("Set resource locker with TaskRunner " + strconv .Itoa (t .Task .ID ))
209
- p .resourceLocker <- & resourceLock {lock : true , holder : t }
210
-
211
- go t .run ()
212
-
213
- p .Queue = p .Queue [1 :]
214
- log .Info ("Task " + strconv .Itoa (t .Task .ID ) + " removed from queue" )
179
+ p .Queue = slices .Delete (p .Queue , i , i + 1 )
180
+ runTask (curr , p )
181
+ }
182
+ }
183
+ }
184
+
185
+ func runTask (task * TaskRunner , p * TaskPool ) {
186
+ log .Info ("Set resource locker with TaskRunner " + strconv .Itoa (task .Task .ID ))
187
+
188
+ p .onTaskRun (task )
189
+
190
+ log .Info ("Task " + strconv .Itoa (task .Task .ID ) + " started" )
191
+ go task .run ()
192
+ }
193
+
194
+ func (p * TaskPool ) onTaskRun (t * TaskRunner ) {
195
+ projTasks , ok := p .activeProj [t .Task .ProjectID ]
196
+ if ! ok {
197
+ projTasks = make (map [int ]* TaskRunner )
198
+ p .activeProj [t .Task .ProjectID ] = projTasks
199
+ }
200
+ projTasks [t .Task .ID ] = t
201
+ p .RunningTasks [t .Task .ID ] = t
202
+ p .aliases [t .Alias ] = t
203
+ }
204
+
205
+ func (p * TaskPool ) onTaskStop (t * TaskRunner ) {
206
+ if p .activeProj [t .Task .ProjectID ] != nil && p .activeProj [t .Task .ProjectID ][t .Task .ID ] != nil {
207
+ delete (p .activeProj [t .Task .ProjectID ], t .Task .ID )
208
+ if len (p .activeProj [t .Task .ProjectID ]) == 0 {
209
+ delete (p .activeProj , t .Task .ProjectID )
215
210
}
216
211
}
212
+
213
+ delete (p .RunningTasks , t .Task .ID )
214
+ delete (p .aliases , t .Alias )
217
215
}
218
216
219
217
func (p * TaskPool ) blocks (t * TaskRunner ) bool {
@@ -247,14 +245,14 @@ func (p *TaskPool) blocks(t *TaskRunner) bool {
247
245
248
246
func CreateTaskPool (store db.Store ) TaskPool {
249
247
return TaskPool {
250
- Queue : make ([]* TaskRunner , 0 ), // queue of waiting tasks
251
- register : make (chan * TaskRunner ), // add TaskRunner to queue
252
- activeProj : make (map [int ]map [int ]* TaskRunner ),
253
- RunningTasks : make (map [int ]* TaskRunner ), // working tasks
254
- logger : make (chan logRecord , 10000 ), // store log records to database
255
- store : store ,
256
- resourceLocker : make (chan * resourceLock ),
257
- aliases : make (map [string ]* TaskRunner ),
248
+ Queue : make ([]* TaskRunner , 0 ), // queue of waiting tasks
249
+ register : make (chan * TaskRunner ), // add TaskRunner to queue
250
+ activeProj : make (map [int ]map [int ]* TaskRunner ),
251
+ RunningTasks : make (map [int ]* TaskRunner ), // working tasks
252
+ logger : make (chan logRecord , 10000 ), // store log records to database
253
+ store : store ,
254
+ queueEvents : make (chan PoolEvent ),
255
+ aliases : make (map [string ]* TaskRunner ),
258
256
}
259
257
}
260
258
@@ -410,7 +408,6 @@ func (p *TaskPool) AddTask(taskObj db.Task, userID *int, projectID int, needAlia
410
408
411
409
if needAlias {
412
410
taskRunner .Alias = random .String (32 )
413
- p .aliases [taskRunner .Alias ] = & taskRunner
414
411
}
415
412
416
413
err = taskRunner .populateDetails ()
0 commit comments