diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2021-03-25 19:01:14 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2021-03-26 10:07:20 +0100 |
| commit | 5f50b260efb9a858ad1a6c5041a8de08fac0f911 (patch) | |
| tree | 7990f3658b5a3279de4e7f20f64674cdf60c839c /dashboard/app/cache.go | |
| parent | 1e99e36f41fbce4e003dfb8e80810fe0b7da7981 (diff) | |
dashboard/app: update memcache with cron
Building the memcache object with bug stats takes
significant time and periodically slows down user requests.
Update it with cron ahead of time.
Diffstat (limited to 'dashboard/app/cache.go')
| -rw-r--r-- | dashboard/app/cache.go | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/dashboard/app/cache.go b/dashboard/app/cache.go index 574324518..7040f65e8 100644 --- a/dashboard/app/cache.go +++ b/dashboard/app/cache.go @@ -9,6 +9,8 @@ import ( "time" "golang.org/x/net/context" + "google.golang.org/appengine" + "google.golang.org/appengine/log" "google.golang.org/appengine/memcache" ) @@ -20,35 +22,43 @@ type Cached struct { func CacheGet(c context.Context, r *http.Request, ns string) (*Cached, error) { accessLevel := accessLevel(c, r) - key := fmt.Sprintf("%v-%v", ns, accessLevel) v := new(Cached) - _, err := memcache.Gob.Get(c, key, v) + _, err := memcache.Gob.Get(c, cacheKey(ns, accessLevel), v) if err != nil && err != memcache.ErrCacheMiss { return nil, err } if err == nil { return v, nil } - if v, err = buildCached(c, ns, accessLevel); err != nil { + bugs, _, err := loadNamespaceBugs(c, ns) + if err != nil { return nil, err } - item := &memcache.Item{ - Key: key, - Object: v, - Expiration: time.Hour, - } - if err := memcache.Gob.Set(c, item); err != nil { - return nil, err + return buildAndStoreCached(c, bugs, ns, accessLevel) +} + +// cacheUpdate updates memcache every hour (called by cron.yaml). +// Cache update is slow and we don't want to slow down user requests. +func cacheUpdate(w http.ResponseWriter, r *http.Request) { + c := appengine.NewContext(r) + for ns := range config.Namespaces { + bugs, _, err := loadNamespaceBugs(c, ns) + if err != nil { + log.Errorf(c, "failed load ns=%v bugs: %v", ns, err) + continue + } + for _, accessLevel := range []AccessLevel{AccessPublic, AccessUser, AccessAdmin} { + _, err := buildAndStoreCached(c, bugs, ns, accessLevel) + if err != nil { + log.Errorf(c, "failed to build cached for ns=%v access=%v: %v", ns, accessLevel, err) + continue + } + } } - return v, nil } -func buildCached(c context.Context, ns string, accessLevel AccessLevel) (*Cached, error) { +func buildAndStoreCached(c context.Context, bugs []*Bug, ns string, accessLevel AccessLevel) (*Cached, error) { v := &Cached{} - bugs, _, err := loadNamespaceBugs(c, ns) - if err != nil { - return nil, err - } for _, bug := range bugs { switch bug.Status { case BugStatusOpen: @@ -66,5 +76,17 @@ func buildCached(c context.Context, ns string, accessLevel AccessLevel) (*Cached v.Invalid++ } } + item := &memcache.Item{ + Key: cacheKey(ns, accessLevel), + Object: v, + Expiration: 4 * time.Hour, // supposed to be updated by cron every hour + } + if err := memcache.Gob.Set(c, item); err != nil { + return nil, err + } return v, nil } + +func cacheKey(ns string, accessLevel AccessLevel) string { + return fmt.Sprintf("%v-%v", ns, accessLevel) +} |
