diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2019-03-15 15:21:21 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2019-03-17 18:06:44 +0100 |
| commit | 03efedc6d1ffa8d8f76696875571b908cfe2fea1 (patch) | |
| tree | feb302a493671c533b7adff32e88938c27d8e22e | |
| parent | c1fd2f3b4aa8dc263c14ecc1c5bee9e721600407 (diff) | |
dashboard/app: add handler for config migration
updateBugReporting adds missing reporting stages to bugs in a single namespace.
Use with care. There is no undo.
This can be used to migrate datastore to a new config with more reporting stages.
This functionality is intentionally not connected to any handler.
Before invoking it is recommented to stop all connected instances just in case.
| -rw-r--r-- | dashboard/app/admin.go | 69 | ||||
| -rw-r--r-- | dashboard/app/api.go | 17 |
2 files changed, 78 insertions, 8 deletions
diff --git a/dashboard/app/admin.go b/dashboard/app/admin.go index db122297a..ce14a067c 100644 --- a/dashboard/app/admin.go +++ b/dashboard/app/admin.go @@ -80,8 +80,6 @@ func dropNamespace(c context.Context, w http.ResponseWriter, r *http.Request) er return nil } -var _ = dropNamespace // prevent warnings about dead code - func dropNamespaceReportingState(c context.Context, w http.ResponseWriter, ns string, dryRun bool) error { tx := func(c context.Context) error { state, err := loadReportingState(c) @@ -121,3 +119,70 @@ func dropEntities(c context.Context, keys []*datastore.Key, dryRun bool) error { } return nil } + +// updateBugReporting adds missing reporting stages to bugs in a single namespace. +// Use with care. There is no undo. +// This can be used to migrate datastore to a new config with more reporting stages. +// This functionality is intentionally not connected to any handler. +// Before invoking it is recommended to stop all connected instances just in case. +func updateBugReporting(c context.Context, w http.ResponseWriter, r *http.Request) error { + if accessLevel(c, r) != AccessAdmin { + return fmt.Errorf("admin only") + } + ns := r.FormValue("ns") + if ns == "" { + return fmt.Errorf("no ns parameter") + } + var bugs []*Bug + keys, err := datastore.NewQuery("Bug"). + Filter("Namespace=", ns). + GetAll(c, &bugs) + if err != nil { + return err + } + log.Warningf(c, "fetched %v bugs for namespce %v", len(bugs), ns) + cfg := config.Namespaces[ns] + var batchKeys []*datastore.Key + const batchSize = 20 + for i, bug := range bugs { + if len(bug.Reporting) >= len(cfg.Reporting) { + continue + } + batchKeys = append(batchKeys, keys[i]) + if len(batchKeys) == batchSize { + if err := updateBugReportingBatch(c, cfg, batchKeys); err != nil { + return err + } + batchKeys = nil + } + } + if len(batchKeys) != 0 { + if err := updateBugReportingBatch(c, cfg, batchKeys); err != nil { + return err + } + } + return nil +} + +func updateBugReportingBatch(c context.Context, cfg *Config, keys []*datastore.Key) error { + tx := func(c context.Context) error { + bugs := make([]*Bug, len(keys)) + if err := datastore.GetMulti(c, keys, bugs); err != nil { + return err + } + for _, bug := range bugs { + createBugReporting(bug, cfg) + } + _, err := datastore.PutMulti(c, keys, bugs) + return err + } + err := datastore.RunInTransaction(c, tx, &datastore.TransactionOptions{XG: true}) + log.Warningf(c, "updated %v bugs: %v", len(keys), err) + return err +} + +// Prevent warnings about dead code. +var ( + _ = dropNamespace + _ = updateBugReporting +) diff --git a/dashboard/app/api.go b/dashboard/app/api.go index 32cab3871..1f4fea5dd 100644 --- a/dashboard/app/api.go +++ b/dashboard/app/api.go @@ -988,12 +988,7 @@ func createBugForCrash(c context.Context, ns string, req *dashapi.Crash) (*Bug, FirstTime: now, LastTime: now, } - for _, rep := range config.Namespaces[ns].Reporting { - bug.Reporting = append(bug.Reporting, BugReporting{ - Name: rep.Name, - ID: bugReportingHash(bugHash, rep.Name), - }) - } + createBugReporting(bug, config.Namespaces[ns]) if bugKey, err = datastore.Put(c, bugKey, bug); err != nil { return fmt.Errorf("failed to put new bug: %v", err) } @@ -1018,6 +1013,16 @@ func createBugForCrash(c context.Context, ns string, req *dashapi.Crash) (*Bug, return bug, bugKey, nil } +func createBugReporting(bug *Bug, cfg *Config) { + for len(bug.Reporting) < len(cfg.Reporting) { + rep := &cfg.Reporting[len(bug.Reporting)] + bug.Reporting = append(bug.Reporting, BugReporting{ + Name: rep.Name, + ID: bugReportingHash(bug.keyHash(), rep.Name), + }) + } +} + func isActiveBug(c context.Context, bug *Bug) (bool, error) { if bug == nil { return false, nil |
