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

Side by Side Diff: appengine/cmd/milo/buildbot/console.go

Issue 2196453002: Milo: Console view prototype (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@master
Patch Set: Rebase fix 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
(Empty)
1 // Copyright 2016 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package buildbot
6
7 import (
8 "fmt"
9 "strings"
10 "time"
11
12 "github.com/luci/gae/service/datastore"
13 "github.com/luci/luci-go/appengine/cmd/milo/resp"
14 "github.com/luci/luci-go/common/clock"
15 log "github.com/luci/luci-go/common/logging"
16 "github.com/luci/luci-go/common/sync/parallel"
17 "golang.org/x/net/context"
18 )
19
20 // getBuilds fetches all of the recent builds from the datastore.
21 func getFullBuilds(c context.Context, masterName, builderName string, finished b ool) ([]*buildbotBuild, error) {
nodir 2016/08/03 20:26:16 why "Full"?
hinoka 2016/08/03 21:55:39 Not sure, I think it was arbitrary. I guess full
22 // TODO(hinoka): Builder specific structs.
23 ds := datastore.Get(c)
24 q := datastore.NewQuery("buildbotBuild")
25 q = q.Eq("finished", finished)
26 q = q.Eq("master", masterName)
27 q = q.Eq("builder", builderName)
28 q = q.Limit(25) // TODO(hinoka): This should be adjustable
29 q = q.Order("-number")
30 q.Finalize()
31 buildbots := make([]*buildbotBuild, 0, 25)
32 err := ds.GetAll(q, &buildbots)
33 return buildbots, err
34 }
35
36 func GetConsoleBuilds(
37 c context.Context, builders []resp.BuilderRef, commits []string) (
38 [][]*resp.ConsoleBuild, error) {
39
40 // First, fetch all the master entries referenced.
41 // TODO(hinoka): Parallel fetch.
42 masters := map[string]*buildbotMaster{}
43 for _, builder := range builders {
nodir 2016/08/03 20:26:17 this loop may take a lot of time because of master
hinoka 2016/08/03 21:55:39 Actually this entire loop isn't used... I forgot w
44 f := strings.SplitN(builder.Name, "/", 2)
nodir 2016/08/03 20:26:17 validate that len(f) == 2, return error if not so
hinoka 2016/08/03 21:55:39 Deleted
45 masterName := f[0]
46 if builder.Module != "buildbot" {
47 panic(fmt.Errorf("Module %s is not buildbot", builder.Mo dule))
48 }
49 if _, ok := masters[masterName]; !ok {
50 master, internal, t, err := getMasterJSON(c, masterName)
51 if err != nil {
52 return nil, err
53 }
54 if t.Before(clock.Now(c).Add(-time.Minute * 5)) {
55 return nil, fmt.Errorf("Data for master is outda ted, last updated %s", t)
56 }
57 if internal {
58 return nil, fmt.Errorf("Internal masters not sup ported")
nodir 2016/08/03 20:26:17 if someone defines a config that references an int
hinoka 2016/08/03 21:55:39 Acknowledged. Probably should just treat the build
59 }
60 masters[masterName] = master
61 }
62 }
63
64 results := make([][]*resp.ConsoleBuild, len(commits))
65 for i := range results {
66 results[i] = make([]*resp.ConsoleBuild, len(builders))
67 }
68 // Reuse the builder code. This is kind of a hack but it's okay for now.
69 err := parallel.FanOutIn(func(taskC chan<- func() error) {
70 for i, builder := range builders {
71 i := i // How do scopes werk
72 f := strings.SplitN(builder.Name, "/", 2)
73 master := f[0]
74 builderName := f[1]
nodir 2016/08/03 20:26:16 this will panic if builder.Name does not have a sl
hinoka 2016/08/03 21:55:39 Done.
75 taskC <- func() error {
76 t1 := clock.Now(c)
77 builds, err := getFullBuilds(c, master, builderN ame, true)
nodir 2016/08/03 20:26:16 it won't show running builds? also does not show a
hinoka 2016/08/03 21:55:39 Yes that is true, but it hasn't been a problem for
nodir 2016/08/04 23:13:12 ok, makes sense now
78 if err != nil {
79 return err
80 }
81 t2 := clock.Now(c)
82 var currentStatus *resp.Status
83 for j, commit := range commits {
84 for _, build := range builds {
85 if build.Sourcestamp.Revision == commit {
nodir 2016/08/03 20:26:17 this is O(n^2) make a map commit->j before fanOutI
hinoka 2016/08/03 21:55:39 Logic for filling in-between builds on L97 would b
86 results[j][i] = &resp.Co nsoleBuild{
nodir 2016/08/03 20:26:17 this code is racy: it mutates results[j] in differ
hinoka 2016/08/03 21:55:39 Each goroutine fully owns a space in [i], so I don
nodir 2016/08/04 23:13:12 Acknowledged.
87 Link: &resp.Link {
88 Label: s trings.Join(build.Text, " "),
89 URL: fmt .Sprintf(
90 "/buildbot/%s/%s/%d", master, builderName, build.Number),
91 },
92 Status: build.to Status(),
93 }
94 currentStatus = &results [j][i].Status
95 }
96 }
97 if currentStatus != nil && results[j][i] == nil {
98 results[j][i] = &resp.ConsoleBui ld{Status: *currentStatus}
nodir 2016/08/03 20:26:17 I don't understand this logic. It might be simpler
hinoka 2016/08/03 21:55:39 Each goroutine processes a single builder. This j
nodir 2016/08/04 23:13:12 this does not sound correct. if there was no build
99 }
100 }
101 log.Debugf(c,
102 "Builder %s took %s to query, %s to comp ute.", builderName,
103 t2.Sub(t1), clock.Since(c, t2))
104 return nil
105 }
106 }
107 })
108
109 return results, err
110
nodir 2016/08/03 20:26:17 remove blank line
hinoka 2016/08/03 21:55:39 Done.
111 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698