@@ -13,7 +13,6 @@ import (
13
13
"errors"
14
14
"flag"
15
15
"fmt"
16
- "io"
17
16
"log"
18
17
"net"
19
18
"net/http"
@@ -43,17 +42,19 @@ func init() {
43
42
http .Handle ("/" , http .FileServer (http .Dir ("./static/" )))
44
43
http .HandleFunc ("/favicon.ico" , faviconHandler )
45
44
http .Handle ("/release" , hstsHandler (func (w http.ResponseWriter , r * http.Request ) { servePage (w , r , "release" ) }))
46
- http .Handle ("/update" , ctxHandler (update ))
47
45
}
48
46
49
47
func main () {
50
48
var (
51
49
listen = flag .String ("listen" , "localhost:6343" , "listen address" )
52
50
devTLSPort = flag .Int ("dev-tls-port" , 0 , "if non-zero, port number to run localhost self-signed TLS server" )
53
51
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" )
54
53
)
55
54
flag .Parse ()
56
55
56
+ go updateLoop (* updateInterval )
57
+
57
58
ln , err := net .Listen ("tcp" , * listen )
58
59
if err != nil {
59
60
log .Fatalf ("Error listening on %s: %v\n " , * listen , err )
@@ -74,6 +75,16 @@ func main() {
74
75
log .Fatal (<- errc )
75
76
}
76
77
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
+
77
88
func serveDevTLS (port int ) error {
78
89
ln , err := net .Listen ("tcp" , "localhost:" + strconv .Itoa (port ))
79
90
if err != nil {
@@ -152,43 +163,27 @@ func hstsHandler(fn http.HandlerFunc) http.Handler {
152
163
})
153
164
}
154
165
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
-
171
166
type page struct {
172
167
// Content is the complete HTML of the page.
173
- Content []byte `datastore:"content,noindex"`
168
+ Content []byte
174
169
}
175
170
176
171
var (
177
172
pageStore = map [string ]* page {}
178
173
pageStoreMu sync.Mutex
179
174
)
180
175
181
- func getPage (ctx context. Context , name string ) (* page , error ) {
176
+ func getPage (name string ) (* page , error ) {
182
177
pageStoreMu .Lock ()
183
178
defer pageStoreMu .Unlock ()
184
179
p , ok := pageStore [name ]
185
180
if ok {
186
181
return p , nil
187
182
}
188
- return & page {} , fmt .Errorf ("page key %s not found" , name )
183
+ return nil , fmt .Errorf ("page key %s not found" , name )
189
184
}
190
185
191
- func writePage (ctx context. Context , pageStr string , content []byte ) error {
186
+ func writePage (pageStr string , content []byte ) error {
192
187
pageStoreMu .Lock ()
193
188
defer pageStoreMu .Unlock ()
194
189
entity := & page {
@@ -199,11 +194,10 @@ func writePage(ctx context.Context, pageStr string, content []byte) error {
199
194
}
200
195
201
196
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 )
204
198
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 )
207
201
return
208
202
}
209
203
w .Header ().Set ("Content-Type" , "text/html; charset=utf-8" )
@@ -224,36 +218,33 @@ func (ct *countTransport) Count() int64 {
224
218
return atomic .LoadInt64 (& ct .count )
225
219
}
226
220
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 ()
229
224
if err != nil {
230
225
return err
231
226
}
232
- gzdata , _ := getCache (ctx , "gzdata" )
227
+ gzdata , _ := getCache ("gzdata" )
228
+
229
+ ctx := context .Background ()
233
230
ct := & countTransport {newTransport (ctx ), 0 }
234
231
gh := godash .NewGitHubClient ("golang/go" , token , ct )
235
232
defer func () {
236
233
log .Printf ("Sent %d requests to GitHub" , ct .Count ())
237
234
}()
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 )}
243
235
244
236
data , err := parseData (gzdata )
245
237
if err != nil {
246
238
return err
247
239
}
248
240
249
241
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 )
252
243
}
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 )
257
248
}
258
249
259
250
var output bytes.Buffer
@@ -265,10 +256,10 @@ func update(ctx context.Context, w http.ResponseWriter, _ *http.Request) error {
265
256
var html bytes.Buffer
266
257
godash .PrintHTML (& html , output .String ())
267
258
268
- if err := writePage (ctx , kind , html .Bytes ()); err != nil {
259
+ if err := writePage (kind , html .Bytes ()); err != nil {
269
260
return err
270
261
}
271
- return writeCache (ctx , "gzdata" , & data )
262
+ return writeCache ("gzdata" , & data )
272
263
}
273
264
274
265
func newTransport (ctx context.Context ) http.RoundTripper {
0 commit comments