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:
parent
36f7c537c7
commit
40817d5f2c
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue