Chromium Code Reviews| Index: logdog/server/service/config/opts.go |
| diff --git a/logdog/server/service/config/opts.go b/logdog/server/service/config/opts.go |
| index 1ac0863f6fff7dd6eecde38a4c7f1927805b9aec..bc9a91039292486471a5dc70962d687d7a9dd798 100644 |
| --- a/logdog/server/service/config/opts.go |
| +++ b/logdog/server/service/config/opts.go |
| @@ -7,6 +7,11 @@ package config |
| import ( |
| "time" |
| + "github.com/luci/luci-go/appengine/datastorecache" |
| + log "github.com/luci/luci-go/common/logging" |
| + "github.com/luci/luci-go/common/sync/mutexpool" |
| + "github.com/luci/luci-go/luci_config/appengine/backend/datastore" |
| + "github.com/luci/luci-go/luci_config/appengine/gaeconfig" |
| "github.com/luci/luci-go/luci_config/server/cfgclient/backend" |
| "github.com/luci/luci-go/luci_config/server/cfgclient/backend/caching" |
| @@ -17,6 +22,12 @@ import ( |
| type CacheOptions struct { |
| // CacheExpiration is the amount of time that a config entry should be cached. |
| CacheExpiration time.Duration |
| + |
| + // DatastoreCacheAvailable, if true, indicates that requisite services for |
| + // datastore cache access are installed in the Context. This requires: |
| + // - A luci/gae datastore service instnace |
| + // - A settings service instance, presumably gaesettings. |
| + DatastoreCacheAvailable bool |
| } |
| // WrapBackend wraps the supplied backend with caching as appropriately |
| @@ -26,6 +37,33 @@ func (o *CacheOptions) WrapBackend(c context.Context, base backend.B) context.Co |
| // Start with our base Backend. |
| be := base |
| + // If our datastore cache is available, fetch settings to see if it's |
| + // enabled. |
| + if o.DatastoreCacheAvailable { |
| + switch s, err := gaeconfig.FetchCachedSettings(c); err { |
| + case nil: |
| + // Successfully fetched settings, is our datastore cache enabled? |
| + switch s.DatastoreCacheMode { |
| + case gaeconfig.DSCacheEnabled, gaeconfig.DSCacheStrict: |
| + // Datastore cache is enabled, add a caching backend layer. |
| + exp := time.Duration(s.CacheExpirationSec) * time.Second |
| + if exp > 0 { |
| + // The cache is enable. Install it into our backend. |
|
iannucci
2017/01/21 00:32:23
enabled
dnj
2017/01/21 02:00:02
Done.
|
| + locker := &dsCacheLocker{} |
| + dsCfg := datastore.Config{ |
| + RefreshInterval: exp, |
| + FailOpen: s.DatastoreCacheMode == gaeconfig.DSCacheEnabled, |
| + LockerFunc: func(context.Context) datastorecache.Locker { return locker }, |
|
iannucci
2017/01/21 00:32:24
I don't suppose it would make sense to have a Lock
dnj
2017/01/21 02:00:02
Acknowledged.
|
| + } |
| + be = dsCfg.Backend(be) |
| + } |
| + } |
| + |
| + default: |
| + log.WithError(err).Debugf(c, "Failed to fetch datastore cache settings.") |
|
iannucci
2017/01/21 00:32:23
Debug? Warning?
dnj
2017/01/21 02:00:02
Warning is fine.
|
| + } |
| + } |
| + |
| // Add a proccache-based config cache. |
| if o.CacheExpiration > 0 { |
| be = caching.ProcCache(be, o.CacheExpiration) |
| @@ -34,3 +72,14 @@ func (o *CacheOptions) WrapBackend(c context.Context, base backend.B) context.Co |
| return be |
| }) |
| } |
| + |
| +type dsCacheLocker struct { |
| + p mutexpool.P |
| +} |
| + |
| +func (l *dsCacheLocker) TryWithLock(c context.Context, key string, fn func(context.Context) error) (err error) { |
| + l.p.WithMutex(key, func() { |
| + err = fn(c) |
| + }) |
| + return |
| +} |