| OLD | NEW |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package buildbucket | 5 package buildbucket |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "encoding/json" | 8 "encoding/json" |
| 9 "fmt" | 9 "fmt" |
| 10 "net/url" | 10 "net/url" |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 target.FinishedBuilds = append(target.FinishedBu
ilds, mb) | 212 target.FinishedBuilds = append(target.FinishedBu
ilds, mb) |
| 213 } | 213 } |
| 214 | 214 |
| 215 default: | 215 default: |
| 216 panic("impossible") | 216 panic("impossible") |
| 217 } | 217 } |
| 218 } | 218 } |
| 219 return nil | 219 return nil |
| 220 } | 220 } |
| 221 | 221 |
| 222 type builderQuery struct { |
| 223 Server string |
| 224 Bucket string |
| 225 Builder string |
| 226 Limit int |
| 227 } |
| 228 |
| 222 // builderImpl is the implementation for getting a milo builder page from buildb
ucket. | 229 // builderImpl is the implementation for getting a milo builder page from buildb
ucket. |
| 223 // if maxCompletedBuilds < 0, 25 is used. | 230 // if maxCompletedBuilds < 0, 25 is used. |
| 224 func builderImpl(c context.Context, server, bucket, builder string, maxCompleted
Builds int) (*resp.Builder, error) { | 231 func builderImpl(c context.Context, q builderQuery) (*resp.Builder, error) { |
| 225 » if maxCompletedBuilds < 0 { | 232 » if q.Limit < 0 { |
| 226 » » maxCompletedBuilds = 20 | 233 » » q.Limit = 20 |
| 227 } | 234 } |
| 228 | 235 |
| 229 result := &resp.Builder{ | 236 result := &resp.Builder{ |
| 230 » » Name: builder, | 237 » » Name: q.Builder, |
| 231 } | 238 } |
| 232 » if server == "debug" { | 239 » if q.Server == "debug" { |
| 233 » » return result, getDebugBuilds(c, bucket, builder, maxCompletedBu
ilds, result) | 240 » » return result, getDebugBuilds(c, q.Bucket, q.Builder, q.Limit, r
esult) |
| 234 } | 241 } |
| 235 » client, err := newBuildbucketClient(c, server) | 242 » client, err := newBuildbucketClient(c, q.Server) |
| 236 if err != nil { | 243 if err != nil { |
| 237 return nil, err | 244 return nil, err |
| 238 } | 245 } |
| 239 | 246 |
| 240 fetch := func(target *[]*resp.BuildSummary, status string, count int) er
ror { | 247 fetch := func(target *[]*resp.BuildSummary, status string, count int) er
ror { |
| 241 » » builds, err := fetchBuilds(c, client, bucket, builder, status, c
ount) | 248 » » builds, err := fetchBuilds(c, client, q.Bucket, q.Builder, statu
s, count) |
| 242 if err != nil { | 249 if err != nil { |
| 243 log.Errorf(c, "Could not fetch builds with status %s: %s
", status, err) | 250 log.Errorf(c, "Could not fetch builds with status %s: %s
", status, err) |
| 244 return err | 251 return err |
| 245 } | 252 } |
| 246 *target = make([]*resp.BuildSummary, len(builds)) | 253 *target = make([]*resp.BuildSummary, len(builds)) |
| 247 for i, bb := range builds { | 254 for i, bb := range builds { |
| 248 (*target)[i] = toMiloBuild(c, bb) | 255 (*target)[i] = toMiloBuild(c, bb) |
| 249 } | 256 } |
| 250 return nil | 257 return nil |
| 251 } | 258 } |
| 252 // fetch pending, current and finished builds concurrently. | 259 // fetch pending, current and finished builds concurrently. |
| 253 // Why not a single request? Because we need different build number | 260 // Why not a single request? Because we need different build number |
| 254 // limits for different statuses. | 261 // limits for different statuses. |
| 255 return result, parallel.FanOutIn(func(work chan<- func() error) { | 262 return result, parallel.FanOutIn(func(work chan<- func() error) { |
| 256 work <- func() error { | 263 work <- func() error { |
| 257 return fetch(&result.PendingBuilds, StatusScheduled, -1) | 264 return fetch(&result.PendingBuilds, StatusScheduled, -1) |
| 258 } | 265 } |
| 259 work <- func() error { | 266 work <- func() error { |
| 260 return fetch(&result.CurrentBuilds, StatusStarted, -1) | 267 return fetch(&result.CurrentBuilds, StatusStarted, -1) |
| 261 } | 268 } |
| 262 work <- func() error { | 269 work <- func() error { |
| 263 » » » return fetch(&result.FinishedBuilds, StatusCompleted, ma
xCompletedBuilds) | 270 » » » return fetch(&result.FinishedBuilds, StatusCompleted, q.
Limit) |
| 264 } | 271 } |
| 265 }) | 272 }) |
| 266 } | 273 } |
| 267 | 274 |
| 268 // parseTimestamp converts buildbucket timestamp in microseconds to time.Time | 275 // parseTimestamp converts buildbucket timestamp in microseconds to time.Time |
| 269 func parseTimestamp(microseconds int64) time.Time { | 276 func parseTimestamp(microseconds int64) time.Time { |
| 270 if microseconds == 0 { | 277 if microseconds == 0 { |
| 271 return time.Time{} | 278 return time.Time{} |
| 272 } | 279 } |
| 273 return time.Unix(microseconds/1e6, microseconds%1e6*1000).UTC() | 280 return time.Unix(microseconds/1e6, microseconds%1e6*1000).UTC() |
| 274 } | 281 } |
| 275 | 282 |
| 276 type newBuildsFirst []*resp.BuildSummary | 283 type newBuildsFirst []*resp.BuildSummary |
| 277 | 284 |
| 278 func (a newBuildsFirst) Len() int { return len(a) } | 285 func (a newBuildsFirst) Len() int { return len(a) } |
| 279 func (a newBuildsFirst) Swap(i, j int) { a[i], a[j] = a[j], a[i] } | 286 func (a newBuildsFirst) Swap(i, j int) { a[i], a[j] = a[j], a[i] } |
| 280 func (a newBuildsFirst) Less(i, j int) bool { | 287 func (a newBuildsFirst) Less(i, j int) bool { |
| 281 return a[i].PendingTime.Started.After(a[j].PendingTime.Started) | 288 return a[i].PendingTime.Started.After(a[j].PendingTime.Started) |
| 282 } | 289 } |
| OLD | NEW |