Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1167)

Unified Diff: luci_config/appengine/backend/memcache/cache.go

Issue 2575383002: Add server/cache support to gaeconfig. (Closed)
Patch Set: Un-collapse. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: luci_config/appengine/backend/memcache/cache.go
diff --git a/luci_config/appengine/backend/memcache/cache.go b/luci_config/appengine/backend/memcache/cache.go
new file mode 100644
index 0000000000000000000000000000000000000000..af39871185a790984a7a9b9d4cefa57e99b6e0cc
--- /dev/null
+++ b/luci_config/appengine/backend/memcache/cache.go
@@ -0,0 +1,99 @@
+// Copyright 2015 The LUCI Authors. All rights reserved.
+// Use of this source code is governed under the Apache License, Version 2.0
+// that can be found in the LICENSE file.
+
+// Package memcache implements a caching config client backend backed by
+// AppEngine's memcache service.
+package memcache
+
+import (
+ "encoding/hex"
+ "time"
+
+ "github.com/luci/luci-go/common/errors"
+ log "github.com/luci/luci-go/common/logging"
+ "github.com/luci/luci-go/luci_config/server/cfgclient/backend"
+ "github.com/luci/luci-go/luci_config/server/cfgclient/backend/caching"
+
+ mc "github.com/luci/gae/service/memcache"
+
+ "golang.org/x/net/context"
+)
+
+const (
+ memCacheSchema = "v1"
+ maxMemCacheSize = 1024 * 1024 // 1MB
+)
+
+// Backend wraps a backend.B instance with a memcache-backed caching layer whose
+// entries expire after exp.
+func Backend(b backend.B, exp time.Duration) backend.B {
+ return &caching.Backend{
+ B: b,
+ CacheGet: func(c context.Context, key caching.Key, l caching.Loader) (*caching.Value, error) {
+ if key.Authority != backend.AsService {
+ return l(c, key, nil)
+ }
+
+ // Is the item already cached?
+ k := memcacheKey(&key)
+ mci, err := mc.GetKey(c, k)
+ switch err {
+ case nil:
+ // Value was cached, successfully retrieved.
+ v, err := caching.DecodeValue(mci.Value())
+ if err != nil {
+ return nil, errors.Annotate(err).Reason("failed to decode cache value from %(key)q").
+ D("key", k).Err()
+ }
+ return v, nil
+
+ case mc.ErrCacheMiss:
+ // Value was not cached. Load from Loader and cache.
+ v, err := l(c, key, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // Attempt to cache the value. If this fails, we'll log a warning and
+ // move on.
+ err = func() error {
+ d, err := v.Encode()
+ if err != nil {
+ return errors.Annotate(err).Reason("failed to encode value").Err()
+ }
+
+ if len(d) > maxMemCacheSize {
+ return errors.Reason("entry exceeds memcache size (%(size)d > %(max)d)").
+ D("size", len(d)).D("max", maxMemCacheSize).Err()
+ }
+
+ item := mc.NewItem(c, k).SetValue(d).SetExpiration(exp)
+ if err := mc.Set(c, item); err != nil {
+ return errors.Annotate(err).Err()
+ }
+ return nil
+ }()
+ if err != nil {
+ log.Fields{
+ log.ErrorKey: err,
+ "key": k,
+ }.Warningf(c, "Failed to cache config.")
+ }
+
+ // Return the loaded value.
+ return v, nil
+
+ default:
+ // Unknown memcache error.
+ log.Fields{
+ log.ErrorKey: err,
+ "key": k,
+ }.Warningf(c, "Failed to decode memcached config.")
+ return l(c, key, nil)
+ }
+ },
+ }
+}
+
+func memcacheKey(key *caching.Key) string { return hex.EncodeToString(key.ParamHash()) }
« no previous file with comments | « logdog/server/collector/coordinator/coordinator.go ('k') | luci_config/appengine/backend/memcache/cache_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698