aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-10-02 13:10:14 +0200
committerDmitry Vyukov <dvyukov@google.com>2018-10-10 13:40:22 +0200
commit7eaec1b83e32fff76cb825b6891a5c1f0c67fe2b (patch)
tree55b1d5ae8ab546e1c76c03ab2b4219fea1e4ea52
parent5b11ac2c91d99eababa8f04c7e2f9484c0763b53 (diff)
dashboard/app: fetch bugs in batches
We are seeing lots of datastore timeout errors during bug fetch. It's a bad idea to fetch thousands of bugs in one query, so fetch them in batches of 1000 bugs. Hopefully will reduce rate of errors.
-rw-r--r--dashboard/app/reporting.go71
1 files changed, 44 insertions, 27 deletions
diff --git a/dashboard/app/reporting.go b/dashboard/app/reporting.go
index 1bb08ffc2..0fd2d7aa3 100644
--- a/dashboard/app/reporting.go
+++ b/dashboard/app/reporting.go
@@ -294,38 +294,55 @@ func managersToRepos(c context.Context, ns string, managers []string) []string {
return repos
}
+func foreachBug(c context.Context, fn func(bug *Bug) error) error {
+ const batchSize = 1000
+ for offset := 0; ; offset += batchSize {
+ var bugs []*Bug
+ _, err := datastore.NewQuery("Bug").
+ Offset(offset).
+ Limit(batchSize).
+ GetAll(c, &bugs)
+ if err != nil {
+ return fmt.Errorf("foreachBug: failed to query bugs: %v", err)
+ }
+ for _, bug := range bugs {
+ if err := fn(bug); err != nil {
+ return err
+ }
+ }
+ if len(bugs) < batchSize {
+ return nil
+ }
+ }
+}
+
// reportingPollClosed is called by backends to get list of closed bugs.
func reportingPollClosed(c context.Context, ids []string) ([]string, error) {
- var bugs []*Bug
- _, err := datastore.NewQuery("Bug").
- GetAll(c, &bugs)
- if err != nil {
- log.Errorf(c, "%v", err)
- return nil, nil
- }
- bugMap := make(map[string]*Bug)
- for _, bug := range bugs {
- for i := range bug.Reporting {
- bugMap[bug.Reporting[i].ID] = bug
- }
+ idMap := make(map[string]bool, len(ids))
+ for _, id := range ids {
+ idMap[id] = true
}
var closed []string
- for _, id := range ids {
- bug := bugMap[id]
- if bug == nil {
- continue
- }
- bugReporting, _ := bugReportingByID(bug, id)
- bug, err = canonicalBug(c, bug)
- if err != nil {
- log.Errorf(c, "%v", err)
- continue
- }
- if bug.Status >= BugStatusFixed || !bugReporting.Closed.IsZero() {
- closed = append(closed, id)
+ err := foreachBug(c, func(bug *Bug) error {
+ for i := range bug.Reporting {
+ bugReporting := &bug.Reporting[i]
+ if !idMap[bugReporting.ID] {
+ continue
+ }
+ var err error
+ bug, err = canonicalBug(c, bug)
+ if err != nil {
+ log.Errorf(c, "%v", err)
+ break
+ }
+ if bug.Status >= BugStatusFixed || !bugReporting.Closed.IsZero() {
+ closed = append(closed, bugReporting.ID)
+ }
+ break
}
- }
- return closed, nil
+ return nil
+ })
+ return closed, err
}
// incomingCommand is entry point to bug status updates.