Skip to content

Commit 9a31848

Browse files
committed
devapp: add ticker to update dashboard data in place of /update
Updates golang/go#20691 Change-Id: I3c691c647860d541d53497c9923383421a5d2298 Reviewed-on: https://go-review.googlesource.com/46837 Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent 69f93e2 commit 9a31848

File tree

3 files changed

+42
-62
lines changed

3 files changed

+42
-62
lines changed

devapp/cache.go

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package main
77
import (
88
"bytes"
99
"compress/gzip"
10-
"context"
1110
"encoding/gob"
1211
"fmt"
1312
"log"
@@ -19,9 +18,8 @@ import (
1918
// A Cache contains serialized data for dashboards.
2019
type Cache struct {
2120
// Value contains a gzipped gob'd serialization of the object
22-
// to be cached. It must be []byte to avail ourselves of the
23-
// datastore's 1 MB size limit.
24-
Value []byte `datastore:"value,noindex"`
21+
// to be cached.
22+
Value []byte
2523
}
2624

2725
var (
@@ -48,15 +46,7 @@ func unpackCache(cache *Cache, data interface{}) error {
4846
return nil
4947
}
5048

51-
func loadCache(ctx context.Context, name string, data interface{}) error {
52-
cache, err := getCache(ctx, name)
53-
if err != nil {
54-
return err
55-
}
56-
return unpackCache(cache, data)
57-
}
58-
59-
func writeCache(ctx context.Context, name string, data interface{}) error {
49+
func writeCache(name string, data interface{}) error {
6050
var cache Cache
6151
var cacheout bytes.Buffer
6252
cachegz := gzip.NewWriter(&cacheout)
@@ -69,17 +59,17 @@ func writeCache(ctx context.Context, name string, data interface{}) error {
6959
}
7060
cache.Value = cacheout.Bytes()
7161
log.Printf("Cache %q update finished; writing %d bytes", name, cacheout.Len())
72-
return putCache(ctx, name, &cache)
62+
return putCache(name, &cache)
7363
}
7464

75-
func putCache(_ context.Context, name string, c *Cache) error {
65+
func putCache(name string, c *Cache) error {
7666
dstoreMu.Lock()
7767
defer dstoreMu.Unlock()
7868
dstore[name] = c
7969
return nil
8070
}
8171

82-
func getCache(_ context.Context, name string) (*Cache, error) {
72+
func getCache(name string) (*Cache, error) {
8373
dstoreMu.Lock()
8474
defer dstoreMu.Unlock()
8575
cache, ok := dstore[name]

devapp/devapp.go

Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"errors"
1414
"flag"
1515
"fmt"
16-
"io"
1716
"log"
1817
"net"
1918
"net/http"
@@ -43,17 +42,19 @@ func init() {
4342
http.Handle("/", http.FileServer(http.Dir("./static/")))
4443
http.HandleFunc("/favicon.ico", faviconHandler)
4544
http.Handle("/release", hstsHandler(func(w http.ResponseWriter, r *http.Request) { servePage(w, r, "release") }))
46-
http.Handle("/update", ctxHandler(update))
4745
}
4846

4947
func main() {
5048
var (
5149
listen = flag.String("listen", "localhost:6343", "listen address")
5250
devTLSPort = flag.Int("dev-tls-port", 0, "if non-zero, port number to run localhost self-signed TLS server")
5351
autocertBucket = flag.String("autocert-bucket", "", "if non-empty, listen on port 443 and serve a LetsEncrypt TLS cert using this Google Cloud Storage bucket as a cache")
52+
updateInterval = flag.Duration("update-interval", 5*time.Minute, "how often to update the dashboard data")
5453
)
5554
flag.Parse()
5655

56+
go updateLoop(*updateInterval)
57+
5758
ln, err := net.Listen("tcp", *listen)
5859
if err != nil {
5960
log.Fatalf("Error listening on %s: %v\n", *listen, err)
@@ -74,6 +75,16 @@ func main() {
7475
log.Fatal(<-errc)
7576
}
7677

78+
func updateLoop(interval time.Duration) {
79+
ticker := time.NewTicker(interval)
80+
for {
81+
if err := update(); err != nil {
82+
log.Printf("update: %v", err)
83+
}
84+
<-ticker.C
85+
}
86+
}
87+
7788
func serveDevTLS(port int) error {
7889
ln, err := net.Listen("tcp", "localhost:"+strconv.Itoa(port))
7990
if err != nil {
@@ -152,43 +163,27 @@ func hstsHandler(fn http.HandlerFunc) http.Handler {
152163
})
153164
}
154165

155-
func ctxHandler(fn func(ctx context.Context, w http.ResponseWriter, r *http.Request) error) http.Handler {
156-
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
157-
ctx := r.Context()
158-
if err := fn(ctx, w, r); err != nil {
159-
log.Printf("handler failed: %v", err)
160-
http.Error(w, err.Error(), 500)
161-
}
162-
})
163-
}
164-
165-
func logFn(ctx context.Context, w io.Writer) func(string, ...interface{}) {
166-
return func(format string, args ...interface{}) {
167-
log.Printf(format, args...)
168-
}
169-
}
170-
171166
type page struct {
172167
// Content is the complete HTML of the page.
173-
Content []byte `datastore:"content,noindex"`
168+
Content []byte
174169
}
175170

176171
var (
177172
pageStore = map[string]*page{}
178173
pageStoreMu sync.Mutex
179174
)
180175

181-
func getPage(ctx context.Context, name string) (*page, error) {
176+
func getPage(name string) (*page, error) {
182177
pageStoreMu.Lock()
183178
defer pageStoreMu.Unlock()
184179
p, ok := pageStore[name]
185180
if ok {
186181
return p, nil
187182
}
188-
return &page{}, fmt.Errorf("page key %s not found", name)
183+
return nil, fmt.Errorf("page key %s not found", name)
189184
}
190185

191-
func writePage(ctx context.Context, pageStr string, content []byte) error {
186+
func writePage(pageStr string, content []byte) error {
192187
pageStoreMu.Lock()
193188
defer pageStoreMu.Unlock()
194189
entity := &page{
@@ -199,11 +194,10 @@ func writePage(ctx context.Context, pageStr string, content []byte) error {
199194
}
200195

201196
func servePage(w http.ResponseWriter, r *http.Request, pageStr string) {
202-
ctx := r.Context()
203-
entity, err := getPage(ctx, pageStr)
197+
entity, err := getPage(pageStr)
204198
if err != nil {
205-
log.Printf("getPage(ctx, %s) = %v", pageStr, err)
206-
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
199+
log.Printf("getPage(%s) = %v", pageStr, err)
200+
http.NotFound(w, r)
207201
return
208202
}
209203
w.Header().Set("Content-Type", "text/html; charset=utf-8")
@@ -224,36 +218,33 @@ func (ct *countTransport) Count() int64 {
224218
return atomic.LoadInt64(&ct.count)
225219
}
226220

227-
func update(ctx context.Context, w http.ResponseWriter, _ *http.Request) error {
228-
token, err := getToken(ctx)
221+
func update() error {
222+
log.Printf("Updating dashboard data...")
223+
token, err := getToken()
229224
if err != nil {
230225
return err
231226
}
232-
gzdata, _ := getCache(ctx, "gzdata")
227+
gzdata, _ := getCache("gzdata")
228+
229+
ctx := context.Background()
233230
ct := &countTransport{newTransport(ctx), 0}
234231
gh := godash.NewGitHubClient("golang/go", token, ct)
235232
defer func() {
236233
log.Printf("Sent %d requests to GitHub", ct.Count())
237234
}()
238-
ger := gerrit.NewClient("https://go-review.googlesource.com", gerrit.NoAuth)
239-
// Without a deadline, urlfetch will use a 5s timeout which is too slow for Gerrit.
240-
gerctx, cancel := context.WithTimeout(ctx, 9*time.Minute)
241-
defer cancel()
242-
ger.HTTPClient = &http.Client{Transport: newTransport(gerctx)}
243235

244236
data, err := parseData(gzdata)
245237
if err != nil {
246238
return err
247239
}
248240

249241
if err := data.Reviewers.LoadGithub(ctx, gh); err != nil {
250-
log.Printf("failed to load reviewers: %v", err)
251-
return err
242+
return fmt.Errorf("failed to load reviewers: %v", err)
252243
}
253-
l := logFn(ctx, w)
254-
if err := data.FetchData(gerctx, gh, ger, l, 7, false, false); err != nil {
255-
log.Printf("failed to fetch data: %v", err)
256-
return err
244+
ger := gerrit.NewClient("https://go-review.googlesource.com", gerrit.NoAuth)
245+
246+
if err := data.FetchData(ctx, gh, ger, log.Printf, 7, false, false); err != nil {
247+
return fmt.Errorf("failed to fetch data: %v", err)
257248
}
258249

259250
var output bytes.Buffer
@@ -265,10 +256,10 @@ func update(ctx context.Context, w http.ResponseWriter, _ *http.Request) error {
265256
var html bytes.Buffer
266257
godash.PrintHTML(&html, output.String())
267258

268-
if err := writePage(ctx, kind, html.Bytes()); err != nil {
259+
if err := writePage(kind, html.Bytes()); err != nil {
269260
return err
270261
}
271-
return writeCache(ctx, "gzdata", &data)
262+
return writeCache("gzdata", &data)
272263
}
273264

274265
func newTransport(ctx context.Context) http.RoundTripper {

devapp/github.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package main
66

77
import (
8-
"context"
98
"flag"
109
"fmt"
1110
"io/ioutil"
@@ -25,7 +24,7 @@ var (
2524
githubOnce sync.Once
2625
)
2726

28-
func getTokenFromFile(ctx context.Context) (string, error) {
27+
func getTokenFromFile() (string, error) {
2928
githubOnce.Do(func() {
3029
const short = ".github-issue-token"
3130
filename := filepath.Clean(os.Getenv("HOME") + "/" + short)
@@ -62,13 +61,13 @@ it at any time.`
6261
return githubToken, githubOnceErr
6362
}
6463

65-
func getToken(ctx context.Context) (string, error) {
64+
func getToken() (string, error) {
6665
if metadata.OnGCE() {
6766
// Re-use maintner-github-token until this is migrated to using the maintner API.
6867
token, err := metadata.ProjectAttributeValue("maintner-github-token")
6968
if len(token) > 0 && err == nil {
7069
return token, nil
7170
}
7271
}
73-
return getTokenFromFile(ctx)
72+
return getTokenFromFile()
7473
}

0 commit comments

Comments
 (0)