dashboard/app: add handler to wipe a builder's results column

Change-Id: Idc3284ff8564a8863d8352890e285babded362cf
Reviewed-on: https://go-review.googlesource.com/1539
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Andrew Gerrand 2014-12-15 12:16:31 +11:00
parent 36f7c537c7
commit 40817d5f2c
3 changed files with 70 additions and 7 deletions

View File

@ -13,7 +13,7 @@ handlers:
static_dir: static static_dir: static
- url: /(|gccgo/|hg/)log/.+ - url: /(|gccgo/|hg/)log/.+
script: _go_app script: _go_app
- url: /(|gccgo/|hg/)(|commit|packages|result|perf-result|tag|todo|perf|perfdetail|perfgraph|updatebenchmark) - url: /(|gccgo/|hg/)(|clear-results|commit|packages|result|perf-result|tag|todo|perf|perfdetail|perfgraph|updatebenchmark)
script: _go_app script: _go_app
- url: /(|gccgo/|hg/)(init|buildtest|key|perflearn|_ah/queue/go/delay) - url: /(|gccgo/|hg/)(init|buildtest|key|perflearn|_ah/queue/go/delay)
script: _go_app script: _go_app

View File

@ -145,7 +145,7 @@ func putCommit(c appengine.Context, com *Commit) error {
// build history and the AppEngine datastore limit of 1mb. // build history and the AppEngine datastore limit of 1mb.
const maxResults = 1000 const maxResults = 1000
// AddResult adds the denormalized Result data to the Commit's Result field. // AddResult adds the denormalized Result data to the Commit's ResultData field.
// It must be called from inside a datastore transaction. // It must be called from inside a datastore transaction.
func (com *Commit) AddResult(c appengine.Context, r *Result) error { func (com *Commit) AddResult(c appengine.Context, r *Result) error {
if err := datastore.Get(c, com.Key(c), com); err != nil { if err := datastore.Get(c, com.Key(c), com); err != nil {
@ -167,6 +167,21 @@ func (com *Commit) AddResult(c appengine.Context, r *Result) error {
return putCommit(c, com) return putCommit(c, com)
} }
// removeResult removes the denormalized Result data from the ResultData field
// for the given builder and go hash.
// It must be called from within the datastore transaction that gets and puts
// the Commit. Note this is slightly different to AddResult, above.
func (com *Commit) RemoveResult(r *Result) {
var rd []string
for _, s := range com.ResultData {
if strings.HasPrefix(s, r.Builder+"|") && strings.HasSuffix(s, "|"+r.GoHash) {
continue
}
rd = append(rd, s)
}
com.ResultData = rd
}
// AddPerfResult remembers that the builder has run the benchmark on the commit. // AddPerfResult remembers that the builder has run the benchmark on the commit.
// It must be called from inside a datastore transaction. // It must be called from inside a datastore transaction.
func (com *Commit) AddPerfResult(c appengine.Context, builder, benchmark string) error { func (com *Commit) AddPerfResult(c appengine.Context, builder, benchmark string) error {
@ -205,7 +220,7 @@ func (c *Commit) Result(builder, goHash string) *Result {
if len(p) != 4 || p[0] != builder || p[3] != goHash { if len(p) != 4 || p[0] != builder || p[3] != goHash {
continue continue
} }
return partsToHash(c, p) return partsToResult(c, p)
} }
return nil return nil
} }
@ -217,7 +232,7 @@ func (c *Commit) Results() (results []*Result) {
if len(p) != 4 { if len(p) != 4 {
continue continue
} }
results = append(results, partsToHash(c, p)) results = append(results, partsToResult(c, p))
} }
return return
} }
@ -371,8 +386,8 @@ func GetCommits(c appengine.Context, startCommitNum, n int) ([]*Commit, error) {
return res, nil return res, nil
} }
// partsToHash converts a Commit and ResultData substrings to a Result. // partsToResult converts a Commit and ResultData substrings to a Result.
func partsToHash(c *Commit, p []string) *Result { func partsToResult(c *Commit, p []string) *Result {
return &Result{ return &Result{
Builder: p[0], Builder: p[0],
Hash: c.Hash, Hash: c.Hash,

View File

@ -793,6 +793,53 @@ func logHandler(w http.ResponseWriter, r *http.Request) {
w.Write(b) w.Write(b)
} }
// clearResultsHandler purges the last commitsPerPage results for the given builder.
// It optionally takes a comma-separated list of specific hashes to clear.
func clearResultsHandler(r *http.Request) (interface{}, error) {
if r.Method != "POST" {
return nil, errBadMethod(r.Method)
}
builder := r.FormValue("builder")
if builder == "" {
return nil, errors.New("must specify a builder")
}
clearAll := r.FormValue("hash") == ""
hash := strings.Split(r.FormValue("hash"), ",")
c := contextForRequest(r)
defer cache.Tick(c)
pkg := (&Package{}).Key(c) // TODO(adg): support clearing sub-repos
err := datastore.RunInTransaction(c, func(c appengine.Context) error {
var coms []*Commit
keys, err := datastore.NewQuery("Commit").
Ancestor(pkg).
Order("-Num").
Limit(commitsPerPage).
GetAll(c, &coms)
if err != nil {
return err
}
var rKeys []*datastore.Key
for _, com := range coms {
if !(clearAll || contains(hash, com.Hash)) {
continue
}
r := com.Result(builder, "")
if r == nil {
continue
}
com.RemoveResult(r)
rKeys = append(rKeys, r.Key(c))
}
_, err = datastore.PutMulti(c, keys, coms)
if err != nil {
return err
}
return datastore.DeleteMulti(c, rKeys)
}, nil)
return nil, err
}
type dashHandler func(*http.Request) (interface{}, error) type dashHandler func(*http.Request) (interface{}, error)
type dashResponse struct { type dashResponse struct {
@ -862,10 +909,11 @@ func init() {
handleFunc("/key", keyHandler) handleFunc("/key", keyHandler)
// authenticated handlers // authenticated handlers
handleFunc("/clear-results", AuthHandler(clearResultsHandler))
handleFunc("/commit", AuthHandler(commitHandler)) handleFunc("/commit", AuthHandler(commitHandler))
handleFunc("/packages", AuthHandler(packagesHandler)) handleFunc("/packages", AuthHandler(packagesHandler))
handleFunc("/result", AuthHandler(resultHandler))
handleFunc("/perf-result", AuthHandler(perfResultHandler)) handleFunc("/perf-result", AuthHandler(perfResultHandler))
handleFunc("/result", AuthHandler(resultHandler))
handleFunc("/tag", AuthHandler(tagHandler)) handleFunc("/tag", AuthHandler(tagHandler))
handleFunc("/todo", AuthHandler(todoHandler)) handleFunc("/todo", AuthHandler(todoHandler))