Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: build_scheduler/go/db/task.go

Issue 2246933002: Add Task DB implementation using a local BoltDB. (Closed) Base URL: https://skia.googlesource.com/buildbot@taskdb-impl-track
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 package db 1 package db
2 2
3 import ( 3 import (
4 "bytes" 4 "bytes"
5 "encoding/gob" 5 "encoding/gob"
6 "fmt" 6 "fmt"
7 "time" 7 "time"
8 8
9 "go.skia.org/infra/go/util" 9 "go.skia.org/infra/go/util"
10 10
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 // that can not be executed on Swarming, but can be added to the DB and 49 // that can not be executed on Swarming, but can be added to the DB and
50 // displayed as if it were a real TaskSpec. 50 // displayed as if it were a real TaskSpec.
51 type Task struct { 51 type Task struct {
52 // Commits are the commits which were tested in this Task. The list may 52 // Commits are the commits which were tested in this Task. The list may
53 // change due to backfilling/bisecting. 53 // change due to backfilling/bisecting.
54 Commits []string 54 Commits []string
55 55
56 // Created is the creation timestamp. 56 // Created is the creation timestamp.
57 Created time.Time 57 Created time.Time
58 58
59 » // Id is a generated unique identifier for this Task instance. Must be U RL-safe. 59 » // Id is a generated unique identifier for this Task instance. Must be
60 » // URL-safe.
60 Id string 61 Id string
61 62
62 // IsolatedOutput is the isolated hash of any outputs produced by this 63 // IsolatedOutput is the isolated hash of any outputs produced by this
63 // Task. Filled in when the task is completed. 64 // Task. Filled in when the task is completed.
64 IsolatedOutput string 65 IsolatedOutput string
65 66
66 // Name is a human-friendly descriptive name for this Task. All Tasks 67 // Name is a human-friendly descriptive name for this Task. All Tasks
67 // generated from the same TaskSpec have the same name. 68 // generated from the same TaskSpec have the same name.
68 Name string 69 Name string
69 70
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 return fmt.Errorf("Unable to parse task creation time for task % s. %v %v", t.Id, err, s) 143 return fmt.Errorf("Unable to parse task creation time for task % s. %v %v", t.Id, err, s)
143 } 144 }
144 145
145 switch s.TaskResult.State { 146 switch s.TaskResult.State {
146 case SWARMING_STATE_BOT_DIED, SWARMING_STATE_CANCELED, SWARMING_STATE_EX PIRED, SWARMING_STATE_TIMED_OUT: 147 case SWARMING_STATE_BOT_DIED, SWARMING_STATE_CANCELED, SWARMING_STATE_EX PIRED, SWARMING_STATE_TIMED_OUT:
147 t.Status = TASK_STATUS_MISHAP 148 t.Status = TASK_STATUS_MISHAP
148 case SWARMING_STATE_PENDING, SWARMING_STATE_RUNNING: 149 case SWARMING_STATE_PENDING, SWARMING_STATE_RUNNING:
149 t.Status = TASK_STATUS_PENDING 150 t.Status = TASK_STATUS_PENDING
150 case SWARMING_STATE_COMPLETED: 151 case SWARMING_STATE_COMPLETED:
151 if s.TaskResult.Failure { 152 if s.TaskResult.Failure {
152 » » » // TODO(benjaminwagner): Choose FAILURE or MISHAP depend ing on ExitCode? 153 » » » // TODO(benjaminwagner): Choose FAILURE or MISHAP depend ing on
154 » » » // ExitCode?
153 t.Status = TASK_STATUS_FAILURE 155 t.Status = TASK_STATUS_FAILURE
154 } else { 156 } else {
155 t.Status = TASK_STATUS_SUCCESS 157 t.Status = TASK_STATUS_SUCCESS
156 } 158 }
157 default: 159 default:
158 return fmt.Errorf("Unknown Swarming State %v in %v", s.TaskResul t.State, s) 160 return fmt.Errorf("Unknown Swarming State %v in %v", s.TaskResul t.State, s)
159 } 161 }
160 162
161 if s.TaskResult.OutputsRef == nil { 163 if s.TaskResult.OutputsRef == nil {
162 t.IsolatedOutput = "" 164 t.IsolatedOutput = ""
(...skipping 19 matching lines...) Expand all
182 if err := gob.NewEncoder(&buf).Encode(t); err != nil { 184 if err := gob.NewEncoder(&buf).Encode(t); err != nil {
183 glog.Fatal(err) 185 glog.Fatal(err)
184 } 186 }
185 var rv Task 187 var rv Task
186 if err := gob.NewDecoder(&buf).Decode(&rv); err != nil { 188 if err := gob.NewDecoder(&buf).Decode(&rv); err != nil {
187 glog.Fatal(err) 189 glog.Fatal(err)
188 } 190 }
189 return &rv 191 return &rv
190 } 192 }
191 193
194 // TaskSlice implements sort.Interface. To sort tasks []*Task, use
195 // sort.Sort(TaskSlice(tasks)).
192 type TaskSlice []*Task 196 type TaskSlice []*Task
193 197
194 func (s TaskSlice) Len() int { return len(s) } 198 func (s TaskSlice) Len() int { return len(s) }
195 199
196 func (s TaskSlice) Less(i, j int) bool { 200 func (s TaskSlice) Less(i, j int) bool {
197 return s[i].Created.Before(s[j].Created) 201 return s[i].Created.Before(s[j].Created)
198 } 202 }
199 203
200 func (s TaskSlice) Swap(i, j int) { 204 func (s TaskSlice) Swap(i, j int) {
201 s[i], s[j] = s[j], s[i] 205 s[i], s[j] = s[j], s[i]
202 } 206 }
207
208 // TaskEncoder encodes Tasks into bytes via GOB encoding. Not safe for
209 // concurrent use.
210 // TODO(benjaminwagner): Encode in parallel.
211 type TaskEncoder struct {
212 err error
213 tasks []*Task
214 result [][]byte
215 }
216
217 // Process encodes the Task into a byte slice that will be returned from Next()
218 // (in arbitrary order). Returns false if Next is certain to return an error.
219 // Caller must ensure t does not change until after the first call to Next().
220 // May not be called after calling Next().
221 func (e *TaskEncoder) Process(t *Task) bool {
222 if e.err != nil {
223 return false
224 }
225 var buf bytes.Buffer
226 if err := gob.NewEncoder(&buf).Encode(t); err != nil {
227 e.err = err
228 e.tasks = nil
229 e.result = nil
230 return false
231 }
232 e.tasks = append(e.tasks, t)
233 e.result = append(e.result, buf.Bytes())
234 return true
235 }
236
237 // Next returns one of the Tasks provided to Process (in arbitrary order) and
238 // its serialized bytes. If any tasks remain, returns the task, the serialized
239 // bytes, nil. If all tasks have been returned, returns nil, nil, nil. If an
240 // error is encountered, returns nil, nil, error.
241 func (e *TaskEncoder) Next() (*Task, []byte, error) {
242 if e.err != nil {
243 return nil, nil, e.err
244 }
245 if len(e.tasks) == 0 {
246 return nil, nil, nil
247 }
248 t := e.tasks[0]
249 e.tasks = e.tasks[1:]
250 serialized := e.result[0]
251 e.result = e.result[1:]
252 return t, serialized, nil
253 }
254
255 // TaskDecoder decodes bytes into Tasks via GOB decoding. Not safe for
256 // concurrent use.
257 // TODO(benjaminwagner): Decode in parallel.
258 type TaskDecoder struct {
259 err error
260 result []*Task
261 }
262
263 // Process decodes the byte slice into a Task and includes it in Result() (in
264 // arbitrary order). Returns false if Result is certain to return an error.
265 // Caller must ensure b does not change until after Result() returns.
266 func (d *TaskDecoder) Process(b []byte) bool {
267 if d.err != nil {
268 return false
269 }
270 var t Task
271 if err := gob.NewDecoder(bytes.NewReader(b)).Decode(&t); err != nil {
272 d.err = err
273 d.result = nil
274 return false
275 }
276 d.result = append(d.result, &t)
277 return true
278 }
279
280 // Result returns all decoded Tasks provided to Process (in arbitrary order), or
281 // any error encountered.
282 func (d *TaskDecoder) Result() ([]*Task, error) {
283 // Allow TaskDecoder to be used without initialization.
284 if d.err == nil && d.result == nil {
285 return []*Task{}, nil
286 }
287 return d.result, d.err
288 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698