diff options
Diffstat (limited to 'misc/dashboard/app/cache/cache.go')
-rw-r--r-- | misc/dashboard/app/cache/cache.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/misc/dashboard/app/cache/cache.go b/misc/dashboard/app/cache/cache.go new file mode 100644 index 000000000..d290ed416 --- /dev/null +++ b/misc/dashboard/app/cache/cache.go @@ -0,0 +1,82 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cache + +import ( + "fmt" + "http" + "time" + + "appengine" + "appengine/memcache" +) + +const ( + nocache = "nocache" + timeKey = "cachetime" + expiry = 600 // 10 minutes +) + +func newTime() uint64 { return uint64(time.Seconds()) << 32 } + +// Now returns the current logical datastore time to use for cache lookups. +func Now(c appengine.Context) uint64 { + t, err := memcache.Increment(c, timeKey, 0, newTime()) + if err != nil { + c.Errorf("cache.Now: %v", err) + return 0 + } + return t +} + +// 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. +func Tick(c appengine.Context) uint64 { + t, err := memcache.Increment(c, timeKey, 1, newTime()) + if err != nil { + c.Errorf("cache.Tick: %v", err) + return 0 + } + return t +} + +// Get fetches data for name at time now from memcache and unmarshals it into +// value. It reports whether it found the cache record and logs any errors to +// the admin console. +func Get(r *http.Request, now uint64, name string, value interface{}) bool { + if now == 0 || r.FormValue(nocache) != "" { + return false + } + c := appengine.NewContext(r) + key := fmt.Sprintf("%s.%d", name, now) + _, err := memcache.JSON.Get(c, key, value) + if err == nil { + c.Debugf("cache hit %q", key) + return true + } + c.Debugf("cache miss %q", key) + if err != memcache.ErrCacheMiss { + c.Errorf("get cache %q: %v", key, err) + } + return false +} + +// Set puts value into memcache under name at time now. +// It logs any errors to the admin console. +func Set(r *http.Request, now uint64, name string, value interface{}) { + if now == 0 || r.FormValue(nocache) != "" { + return + } + c := appengine.NewContext(r) + key := fmt.Sprintf("%s.%d", name, now) + err := memcache.JSON.Set(c, &memcache.Item{ + Key: key, + Object: value, + Expiration: expiry, + }) + if err != nil { + c.Errorf("set cache %q: %v", key, err) + } +} |