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

Side by Side Diff: milo/appengine/buildbot/grpc.go

Issue 2810113002: Milo buildbot builder page: Add pagnation with cursors. (Closed)
Patch Set: train Created 3 years, 8 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
« no previous file with comments | « milo/appengine/buildbot/datastore.go ('k') | milo/appengine/buildbot/html.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 buildbot 5 package buildbot
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "compress/gzip" 9 "compress/gzip"
10 "encoding/json" 10 "encoding/json"
11 11
12 "golang.org/x/net/context" 12 "golang.org/x/net/context"
13 "google.golang.org/grpc" 13 "google.golang.org/grpc"
14 "google.golang.org/grpc/codes" 14 "google.golang.org/grpc/codes"
15 15
16 "github.com/golang/protobuf/ptypes/timestamp" 16 "github.com/golang/protobuf/ptypes/timestamp"
17 » ds "github.com/luci/gae/service/datastore" 17 » "github.com/luci/gae/service/datastore"
18 "github.com/luci/luci-go/common/iotools" 18 "github.com/luci/luci-go/common/iotools"
19 "github.com/luci/luci-go/common/logging" 19 "github.com/luci/luci-go/common/logging"
20 milo "github.com/luci/luci-go/milo/api/proto" 20 milo "github.com/luci/luci-go/milo/api/proto"
21 "github.com/luci/luci-go/server/auth" 21 "github.com/luci/luci-go/server/auth"
22 ) 22 )
23 23
24 // Service is a service implementation that displays BuildBot builds. 24 // Service is a service implementation that displays BuildBot builds.
25 type Service struct{} 25 type Service struct{}
26 26
27 var errNotFoundGRPC = grpc.Errorf(codes.NotFound, "Master Not Found") 27 var errNotFoundGRPC = grpc.Errorf(codes.NotFound, "Master Not Found")
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 if req.Builder == "" { 71 if req.Builder == "" {
72 return nil, grpc.Errorf(codes.InvalidArgument, "No builder speci fied") 72 return nil, grpc.Errorf(codes.InvalidArgument, "No builder speci fied")
73 } 73 }
74 74
75 limit := req.Limit 75 limit := req.Limit
76 if limit == 0 { 76 if limit == 0 {
77 limit = 20 77 limit = 20
78 } 78 }
79 79
80 cu := auth.CurrentUser(c) 80 cu := auth.CurrentUser(c)
81 » logging.Debugf(c, "%s is requesting %s/%s (limit %d)", 81 » logging.Debugf(c, "%s is requesting %s/%s (limit %d, cursor %s)",
82 » » cu.Identity, req.Master, req.Builder, limit) 82 » » cu.Identity, req.Master, req.Builder, limit, req.Cursor)
83 83
84 // Perform an ACL check by fetching the master. 84 // Perform an ACL check by fetching the master.
85 _, err := getMasterEntry(c, req.Master) 85 _, err := getMasterEntry(c, req.Master)
86 switch { 86 switch {
87 case err == errMasterNotFound: 87 case err == errMasterNotFound:
88 return nil, grpc.Errorf(codes.NotFound, "Master not found") 88 return nil, grpc.Errorf(codes.NotFound, "Master not found")
89 case err == errNotAuth: 89 case err == errNotAuth:
90 return nil, grpc.Errorf(codes.Unauthenticated, "Unauthenticated request") 90 return nil, grpc.Errorf(codes.Unauthenticated, "Unauthenticated request")
91 case err != nil: 91 case err != nil:
92 return nil, err 92 return nil, err
93 } 93 }
94 94
95 » q := ds.NewQuery("buildbotBuild") 95 » q := datastore.NewQuery("buildbotBuild")
96 q = q.Eq("master", req.Master). 96 q = q.Eq("master", req.Master).
97 Eq("builder", req.Builder). 97 Eq("builder", req.Builder).
98 Limit(limit). 98 Limit(limit).
99 Order("-number") 99 Order("-number")
100 if req.IncludeCurrent == false { 100 if req.IncludeCurrent == false {
101 q = q.Eq("finished", true) 101 q = q.Eq("finished", true)
102 } 102 }
103 » builds := []*buildbotBuild{} 103 » // Insert the cursor or offset.
104 » err = getBuildQueryBatcher(c).GetAll(c, q, &builds) 104 » if req.Cursor != "" {
105 » » cursor, err := datastore.DecodeCursor(c, req.Cursor)
106 » » if err != nil {
107 » » » return nil, grpc.Errorf(codes.InvalidArgument, "Invalid cursor: %s", err.Error())
108 » » }
109 » » q = q.Start(cursor)
110 » }
111 » builds, nextCursor, err := runBuildsQuery(c, q, int32(req.Limit))
105 if err != nil { 112 if err != nil {
106 return nil, err 113 return nil, err
107 } 114 }
108 115
109 results := make([]*milo.BuildbotBuildJSON, len(builds)) 116 results := make([]*milo.BuildbotBuildJSON, len(builds))
110 for i, b := range builds { 117 for i, b := range builds {
111 updatePostProcessBuild(b) 118 updatePostProcessBuild(b)
112 119
113 // In theory we could do this in parallel, but it doesn't actual ly go faster 120 // In theory we could do this in parallel, but it doesn't actual ly go faster
114 // since AppEngine is single-cored. 121 // since AppEngine is single-cored.
115 bs, err := json.Marshal(b) 122 bs, err := json.Marshal(b)
116 if err != nil { 123 if err != nil {
117 return nil, err 124 return nil, err
118 } 125 }
119 results[i] = &milo.BuildbotBuildJSON{Data: bs} 126 results[i] = &milo.BuildbotBuildJSON{Data: bs}
120 } 127 }
121 » return &milo.BuildbotBuildsJSON{ 128 » buildsJSON := &milo.BuildbotBuildsJSON{
122 Builds: results, 129 Builds: results,
123 » }, nil 130 » }
131 » if nextCursor != nil {
132 » » buildsJSON.Cursor = (*nextCursor).String()
133 » }
134 » return buildsJSON, nil
124 } 135 }
125 136
126 // GetCompressedMasterJSON assembles a CompressedMasterJSON object from the 137 // GetCompressedMasterJSON assembles a CompressedMasterJSON object from the
127 // provided MasterRequest. 138 // provided MasterRequest.
128 func (s *Service) GetCompressedMasterJSON(c context.Context, req *milo.MasterReq uest) ( 139 func (s *Service) GetCompressedMasterJSON(c context.Context, req *milo.MasterReq uest) (
129 *milo.CompressedMasterJSON, error) { 140 *milo.CompressedMasterJSON, error) {
130 141
131 if req.Name == "" { 142 if req.Name == "" {
132 return nil, grpc.Errorf(codes.InvalidArgument, "No master specif ied") 143 return nil, grpc.Errorf(codes.InvalidArgument, "No master specif ied")
133 } 144 }
(...skipping 23 matching lines...) Expand all
157 slave.Runningbuilds = make([]*buildbotBuild, 0, numBuilds) 168 slave.Runningbuilds = make([]*buildbotBuild, 0, numBuilds)
158 for builderName, builds := range slave.RunningbuildsMap { 169 for builderName, builds := range slave.RunningbuildsMap {
159 for _, buildNum := range builds { 170 for _, buildNum := range builds {
160 slave.Runningbuilds = append(slave.Runningbuilds , &buildbotBuild{ 171 slave.Runningbuilds = append(slave.Runningbuilds , &buildbotBuild{
161 Master: req.Name, 172 Master: req.Name,
162 Buildername: builderName, 173 Buildername: builderName,
163 Number: buildNum, 174 Number: buildNum,
164 }) 175 })
165 } 176 }
166 } 177 }
167 » » if err := ds.Get(c, slave.Runningbuilds); err != nil { 178 » » if err := datastore.Get(c, slave.Runningbuilds); err != nil {
168 logging.WithError(err).Errorf(c, 179 logging.WithError(err).Errorf(c,
169 "Encountered error while trying to fetch running builds for %s: %v", 180 "Encountered error while trying to fetch running builds for %s: %v",
170 master.Name, slave.Runningbuilds) 181 master.Name, slave.Runningbuilds)
171 return nil, err 182 return nil, err
172 } 183 }
173 184
174 for _, b := range slave.Runningbuilds { 185 for _, b := range slave.Runningbuilds {
175 updatePostProcessBuild(b) 186 updatePostProcessBuild(b)
176 } 187 }
177 } 188 }
178 189
179 // Also inject cached builds information. 190 // Also inject cached builds information.
180 for builderName, builder := range master.Builders { 191 for builderName, builder := range master.Builders {
181 // Get the most recent 50 buildNums on the builder to simulate w hat the 192 // Get the most recent 50 buildNums on the builder to simulate w hat the
182 // cachedBuilds field looks like from the real buildbot master j son. 193 // cachedBuilds field looks like from the real buildbot master j son.
183 » » q := ds.NewQuery("buildbotBuild"). 194 » » q := datastore.NewQuery("buildbotBuild").
184 Eq("finished", true). 195 Eq("finished", true).
185 Eq("master", req.Name). 196 Eq("master", req.Name).
186 Eq("builder", builderName). 197 Eq("builder", builderName).
187 Limit(50). 198 Limit(50).
188 Order("-number"). 199 Order("-number").
189 KeysOnly(true) 200 KeysOnly(true)
190 var builds []*buildbotBuild 201 var builds []*buildbotBuild
191 err := getBuildQueryBatcher(c).GetAll(c, q, &builds) 202 err := getBuildQueryBatcher(c).GetAll(c, q, &builds)
192 if err != nil { 203 if err != nil {
193 return nil, err 204 return nil, err
(...skipping 19 matching lines...) Expand all
213 224
214 return &milo.CompressedMasterJSON{ 225 return &milo.CompressedMasterJSON{
215 Internal: entry.Internal, 226 Internal: entry.Internal,
216 Modified: &timestamp.Timestamp{ 227 Modified: &timestamp.Timestamp{
217 Seconds: entry.Modified.Unix(), 228 Seconds: entry.Modified.Unix(),
218 Nanos: int32(entry.Modified.Nanosecond()), 229 Nanos: int32(entry.Modified.Nanosecond()),
219 }, 230 },
220 Data: gzbs.Bytes(), 231 Data: gzbs.Bytes(),
221 }, nil 232 }, nil
222 } 233 }
OLDNEW
« no previous file with comments | « milo/appengine/buildbot/datastore.go ('k') | milo/appengine/buildbot/html.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698