dashboard: split key handler into key package, add TimeKey to cache

LGTM=dsymonds
R=golang-codereviews, dsymonds
CC=golang-codereviews
https://golang.org/cl/104780044
This commit is contained in:
Andrew Gerrand 2014-06-02 08:39:03 +10:00
parent 222283a9c8
commit 707c7629cb
4 changed files with 19 additions and 14 deletions

View File

@ -20,6 +20,7 @@ import (
"appengine/datastore" "appengine/datastore"
"cache" "cache"
"key"
) )
const commitsPerPage = 30 const commitsPerPage = 30
@ -789,12 +790,12 @@ func validKey(c appengine.Context, key, builder string) bool {
return isMasterKey(c, key) || key == builderKey(c, builder) return isMasterKey(c, key) || key == builderKey(c, builder)
} }
func isMasterKey(c appengine.Context, key string) bool { func isMasterKey(c appengine.Context, k string) bool {
return appengine.IsDevAppServer() || key == secretKey(c) return appengine.IsDevAppServer() || k == key.Secret(c)
} }
func builderKey(c appengine.Context, builder string) string { func builderKey(c appengine.Context, builder string) string {
h := hmac.New(md5.New, []byte(secretKey(c))) h := hmac.New(md5.New, []byte(key.Secret(c)))
h.Write([]byte(builder)) h.Write([]byte(builder))
return fmt.Sprintf("%x", h.Sum(nil)) return fmt.Sprintf("%x", h.Sum(nil))
} }

View File

@ -12,7 +12,9 @@ import (
"appengine" "appengine"
"appengine/datastore" "appengine/datastore"
"cache" "cache"
"key"
) )
func initHandler(w http.ResponseWriter, r *http.Request) { func initHandler(w http.ResponseWriter, r *http.Request) {
@ -38,7 +40,7 @@ func initHandler(w http.ResponseWriter, r *http.Request) {
} }
// Create secret key. // Create secret key.
secretKey(c) key.Secret(c)
fmt.Fprint(w, "OK") fmt.Fprint(w, "OK")
} }

View File

@ -15,9 +15,11 @@ import (
"appengine/memcache" "appengine/memcache"
) )
// TimeKey specifies the memcache entity that keeps the logical datastore time.
var TimeKey = "cachetime"
const ( const (
nocache = "nocache" nocache = "nocache"
timeKey = "cachetime"
expiry = 600 // 10 minutes expiry = 600 // 10 minutes
) )
@ -25,7 +27,7 @@ func newTime() uint64 { return uint64(time.Now().Unix()) << 32 }
// Now returns the current logical datastore time to use for cache lookups. // Now returns the current logical datastore time to use for cache lookups.
func Now(c appengine.Context) uint64 { func Now(c appengine.Context) uint64 {
t, err := memcache.Increment(c, timeKey, 0, newTime()) t, err := memcache.Increment(c, TimeKey, 0, newTime())
if err != nil { if err != nil {
c.Errorf("cache.Now: %v", err) c.Errorf("cache.Now: %v", err)
return 0 return 0
@ -36,7 +38,7 @@ func Now(c appengine.Context) uint64 {
// Tick sets the current logical datastore time to a never-before-used time // Tick sets the current logical datastore time to a never-before-used time
// and returns that time. It should be called to invalidate the cache. // and returns that time. It should be called to invalidate the cache.
func Tick(c appengine.Context) uint64 { func Tick(c appengine.Context) uint64 {
t, err := memcache.Increment(c, timeKey, 1, newTime()) t, err := memcache.Increment(c, TimeKey, 1, newTime())
if err != nil { if err != nil {
c.Errorf("cache.Tick: %v", err) c.Errorf("cache.Tick: %v", err)
return 0 return 0

View File

@ -4,7 +4,7 @@
// +build appengine // +build appengine
package build package key
import ( import (
"sync" "sync"
@ -15,18 +15,18 @@ import (
var theKey struct { var theKey struct {
sync.RWMutex sync.RWMutex
BuilderKey builderKey
} }
type BuilderKey struct { type builderKey struct {
Secret string Secret string
} }
func (k *BuilderKey) Key(c appengine.Context) *datastore.Key { func (k *builderKey) Key(c appengine.Context) *datastore.Key {
return datastore.NewKey(c, "BuilderKey", "root", 0, nil) return datastore.NewKey(c, "BuilderKey", "root", 0, nil)
} }
func secretKey(c appengine.Context) string { func Secret(c appengine.Context) string {
// check with rlock // check with rlock
theKey.RLock() theKey.RLock()
k := theKey.Secret k := theKey.Secret
@ -43,7 +43,7 @@ func secretKey(c appengine.Context) string {
} }
// fill // fill
if err := datastore.Get(c, theKey.Key(c), &theKey.BuilderKey); err != nil { if err := datastore.Get(c, theKey.Key(c), &theKey.builderKey); err != nil {
if err == datastore.ErrNoSuchEntity { if err == datastore.ErrNoSuchEntity {
// If the key is not stored in datastore, write it. // If the key is not stored in datastore, write it.
// This only happens at the beginning of a new deployment. // This only happens at the beginning of a new deployment.
@ -54,7 +54,7 @@ func secretKey(c appengine.Context) string {
panic("lost key from datastore") panic("lost key from datastore")
} }
theKey.Secret = "gophers rule" theKey.Secret = "gophers rule"
datastore.Put(c, theKey.Key(c), &theKey.BuilderKey) datastore.Put(c, theKey.Key(c), &theKey.builderKey)
return theKey.Secret return theKey.Secret
} }
panic("cannot load builder key: " + err.Error()) panic("cannot load builder key: " + err.Error())