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

Side by Side Diff: appengine/cmd/dm/deps/ensure_graph_data.go

Issue 1537883002: Initial distributor implementation (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@master
Patch Set: self review Created 4 years, 6 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 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 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 deps 5 package deps
6 6
7 import ( 7 import (
8 "errors"
9 "fmt" 8 "fmt"
10 9
11 "golang.org/x/net/context" 10 "golang.org/x/net/context"
12 "google.golang.org/grpc/codes" 11 "google.golang.org/grpc/codes"
13 12
14 "github.com/luci/gae/service/datastore" 13 "github.com/luci/gae/service/datastore"
15 14
16 "github.com/luci/luci-go/common/grpcutil" 15 "github.com/luci/luci-go/common/grpcutil"
17 "github.com/luci/luci-go/common/logging" 16 "github.com/luci/luci-go/common/logging"
18 "github.com/luci/luci-go/common/parallel" 17 "github.com/luci/luci-go/common/parallel"
19 "github.com/luci/luci-go/common/stringset" 18 "github.com/luci/luci-go/common/stringset"
20 19
21 » "github.com/luci/luci-go/common/api/dm/service/v1" 20 » dm "github.com/luci/luci-go/common/api/dm/service/v1"
22 "github.com/luci/luci-go/common/api/dm/template" 21 "github.com/luci/luci-go/common/api/dm/template"
23 22
24 "github.com/luci/luci-go/appengine/tumble" 23 "github.com/luci/luci-go/appengine/tumble"
25 24
25 "github.com/luci/luci-go/appengine/cmd/dm/distributor"
26 "github.com/luci/luci-go/appengine/cmd/dm/model" 26 "github.com/luci/luci-go/appengine/cmd/dm/model"
27 "github.com/luci/luci-go/appengine/cmd/dm/mutate" 27 "github.com/luci/luci-go/appengine/cmd/dm/mutate"
28 ) 28 )
29 29
30 func (d *deps) runEnsureGraphDepsWalk(c context.Context, req *dm.EnsureGraphData Req, newAttempts *dm.AttemptList) (*dm.GraphData, error) { 30 func (d *deps) runEnsureGraphDepsWalk(c context.Context, req *dm.EnsureGraphData Req, newAttempts *dm.AttemptList) (*dm.GraphData, error) {
31 // first lets run a query to load all of the proposed attempts. 31 // first lets run a query to load all of the proposed attempts.
32 wgreq := &dm.WalkGraphReq{ 32 wgreq := &dm.WalkGraphReq{
33 Query: dm.AttemptListQuery(newAttempts), 33 Query: dm.AttemptListQuery(newAttempts),
34 Limit: &dm.WalkGraphReq_Limit{ 34 Limit: &dm.WalkGraphReq_Limit{
35 MaxDepth: 1, 35 MaxDepth: 1,
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 } 214 }
215 215
216 // not all of the attemps exist/are finished, we have to block. 216 // not all of the attemps exist/are finished, we have to block.
217 rsp.Result = nil 217 rsp.Result = nil
218 rsp.ShouldHalt = true 218 rsp.ShouldHalt = true
219 219
220 return tumbleNow(c, &mutate.AddDeps{ 220 return tumbleNow(c, &mutate.AddDeps{
221 Auth: req.ForExecution, 221 Auth: req.ForExecution,
222 Quests: newQuests, 222 Quests: newQuests,
223 // Attempts we think are missing 223 // Attempts we think are missing
224 » » Atmpts: newAttempts, 224 » » Attempts: newAttempts,
225 // Deps we think are missing (>= newAttempts) 225 // Deps we think are missing (>= newAttempts)
226 Deps: missingDeps, 226 Deps: missingDeps,
227 }) 227 })
228 } 228 }
229 229
230 type templateFileKey struct { 230 type templateFileKey struct {
231 project, ref string 231 project, ref string
232 } 232 }
233 233
234 type templateFile struct { 234 type templateFile struct {
(...skipping 26 matching lines...) Expand all
261 if err == nil { 261 if err == nil {
262 return false 262 return false
263 } 263 }
264 if rsp.TemplateError == nil { 264 if rsp.TemplateError == nil {
265 rsp.TemplateError = make([]string, len(req.TemplateQuest )) 265 rsp.TemplateError = make([]string, len(req.TemplateQuest ))
266 } 266 }
267 rsp.TemplateError[i] = err.Error() 267 rsp.TemplateError[i] = err.Error()
268 return true 268 return true
269 } 269 }
270 270
271 dists := map[string]distributor.D{}
272
271 newQuests = make(map[string]*model.Quest, len(req.Quest)+len(req.Templat eQuest)) 273 newQuests = make(map[string]*model.Quest, len(req.Quest)+len(req.Templat eQuest))
272 newAttempts = dm.NewAttemptList(nil) 274 newAttempts = dm.NewAttemptList(nil)
273 275
276 reg := distributor.GetRegistry(c)
277
274 // render all quest descriptions 278 // render all quest descriptions
275 for i, qDesc := range req.Quest { 279 for i, qDesc := range req.Quest {
276 » » var q *model.Quest 280 » » q := model.NewQuest(c, qDesc)
277 » » if q, err = model.NewQuest(c, qDesc); err != nil { 281
278 » » » err = grpcutil.MaybeLogErr(c, err, codes.InvalidArgument , "bad quest description") 282 » » d, ok := dists[qDesc.DistributorConfigName]
283 » » if !ok {
284 » » » if d, _, err = reg.MakeDistributor(c, qDesc.DistributorC onfigName); err != nil {
285 » » » » return
286 » » » }
287 » » » dists[qDesc.DistributorConfigName] = d
288 » » }
289
290 » » if err = d.Validate(qDesc.JsonPayload); err != nil {
291 » » » err = grpcutil.MaybeLogErr(c, err, codes.InvalidArgument ,
292 » » » » "JSON payload is invalid for this distributor co nfiguration.")
279 return 293 return
280 } 294 }
281 295
282 // all provided quest descriptions MUST include at least one att empt 296 // all provided quest descriptions MUST include at least one att empt
283 if _, ok := req.Attempts.To[q.ID]; !ok { 297 if _, ok := req.Attempts.To[q.ID]; !ok {
284 c = logging.SetFields(c, logging.Fields{"id": q.ID, "idx ": i}) 298 c = logging.SetFields(c, logging.Fields{"id": q.ID, "idx ": i})
285 err = grpcutil.MaybeLogErr(c, 299 err = grpcutil.MaybeLogErr(c,
286 » » » » errors.New("Quest entries must have a matching A ttempts entry"), 300 » » » » fmt.Errorf("Quest %d:%q must have a matching Att empts entry", i, q.ID),
dnj (Google) 2016/06/09 18:00:54 Maybe use annotated error?
iannucci 2016/06/15 00:45:58 I will do so in a followup for sure!
287 codes.InvalidArgument, "no matches") 301 codes.InvalidArgument, "no matches")
288 return 302 return
289 } 303 }
290 304
291 if _, ok := newQuests[q.ID]; !ok { 305 if _, ok := newQuests[q.ID]; !ok {
292 newQuests[q.ID] = q 306 newQuests[q.ID] = q
293 } 307 }
294 } 308 }
295 309
296 // copy all normal attempt descriptions 310 // copy all normal attempt descriptions
297 for qid, nums := range req.Attempts.To { 311 for qid, nums := range req.Attempts.To {
298 newNums := &dm.AttemptList_Nums{Nums: make([]uint32, len(nums.Nu ms))} 312 newNums := &dm.AttemptList_Nums{Nums: make([]uint32, len(nums.Nu ms))}
299 copy(newNums.Nums, nums.Nums) 313 copy(newNums.Nums, nums.Nums)
300 newAttempts.To[qid] = newNums 314 newAttempts.To[qid] = newNums
301 } 315 }
302 316
303 // render all templates and template attempts into newQuests 317 // render all templates and template attempts into newQuests
304 templateFiles := templateFileCache{} 318 templateFiles := templateFileCache{}
305 for i := 0; i < len(req.TemplateQuest); i++ { 319 for i := 0; i < len(req.TemplateQuest); i++ {
306 inst := req.TemplateQuest[i] 320 inst := req.TemplateQuest[i]
307 321
308 var vers string 322 var vers string
309 var desc *dm.Quest_Desc 323 var desc *dm.Quest_Desc
310 if desc, vers, err = templateFiles.render(c, inst); setTemplateE rr(i, err) { 324 if desc, vers, err = templateFiles.render(c, inst); setTemplateE rr(i, err) {
311 continue 325 continue
312 } 326 }
313 327 » » if setTemplateErr(i, desc.Normalize()) {
314 » » var q *model.Quest
315 » » q, err = model.NewQuest(c, desc)
316 » » if setTemplateErr(i, err) {
317 continue 328 continue
318 } 329 }
319 330
331 q := model.NewQuest(c, desc)
332
320 rsp.TemplateIds = append(rsp.TemplateIds, dm.NewQuestID(q.ID)) 333 rsp.TemplateIds = append(rsp.TemplateIds, dm.NewQuestID(q.ID))
321 334
322 // if we have any errors going on, might as well skip the rest 335 // if we have any errors going on, might as well skip the rest
323 if len(rsp.TemplateError) > 0 { 336 if len(rsp.TemplateError) > 0 {
324 continue 337 continue
325 } 338 }
326 339
327 anums := newAttempts.To[q.ID] 340 anums := newAttempts.To[q.ID]
328 anums.Nums = append(anums.Nums, req.TemplateAttempt[i].Nums...) 341 anums.Nums = append(anums.Nums, req.TemplateAttempt[i].Nums...)
329 if err := anums.Normalize(); err != nil { 342 if err := anums.Normalize(); err != nil {
(...skipping 10 matching lines...) Expand all
340 Project: inst.Project, Ref: inst.Ref, Version: vers, 353 Project: inst.Project, Ref: inst.Ref, Version: vers,
341 Name: inst.Specifier.TemplateName}) 354 Name: inst.Specifier.TemplateName})
342 } 355 }
343 356
344 return 357 return
345 } 358 }
346 359
347 func (d *deps) EnsureGraphData(c context.Context, req *dm.EnsureGraphDataReq) (r sp *dm.EnsureGraphDataRsp, err error) { 360 func (d *deps) EnsureGraphData(c context.Context, req *dm.EnsureGraphDataReq) (r sp *dm.EnsureGraphDataRsp, err error) {
348 // TODO(riannucci): real non-execution authentication 361 // TODO(riannucci): real non-execution authentication
349 if req.ForExecution != nil { 362 if req.ForExecution != nil {
363 logging.Fields{"execution": req.ForExecution.Id}.Infof(c, "on be half of")
350 _, _, err := model.AuthenticateExecution(c, req.ForExecution) 364 _, _, err := model.AuthenticateExecution(c, req.ForExecution)
351 if err != nil { 365 if err != nil {
352 return nil, grpcutil.MaybeLogErr(c, err, codes.Unauthent icated, "bad execution auth") 366 return nil, grpcutil.MaybeLogErr(c, err, codes.Unauthent icated, "bad execution auth")
353 } 367 }
354 } 368 }
355 369
356 // render any quest descirptions, templates and template attempts into 370 // render any quest descirptions, templates and template attempts into
357 // a single merged set of new quests and new attempts 371 // a single merged set of new quests and new attempts
358 rsp, newQuests, newAttempts, err := renderRequest(c, req) 372 rsp, newQuests, newAttempts, err := renderRequest(c, req)
359 if err != nil || len(rsp.TemplateError) > 0 { 373 if err != nil || len(rsp.TemplateError) > 0 {
360 return 374 return
361 } 375 }
362 376
363 newQuestList := make([]*model.Quest, 0, len(newQuests)) 377 newQuestList := make([]*model.Quest, 0, len(newQuests))
364 for _, q := range newQuests { 378 for _, q := range newQuests {
365 newQuestList = append(newQuestList, q) 379 newQuestList = append(newQuestList, q)
366 } 380 }
367 381
368 err = d.ensureGraphData(c, req, newQuestList, newAttempts, rsp) 382 err = d.ensureGraphData(c, req, newQuestList, newAttempts, rsp)
369 383
370 return 384 return
371 } 385 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698