| Index: logdog/server/service/config/opts.go
|
| diff --git a/logdog/server/service/config/opts.go b/logdog/server/service/config/opts.go
|
| index d26518b02a089326698795498fb683e1da2b8184..b62de5134dd1f339136f1c1c98c045a015d0c4fb 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"
|
|
|
| @@ -20,6 +25,12 @@ type CacheOptions struct {
|
| // If this value is <= 0, no configuration caching will be enabled. This
|
| // should not be set for production systems.
|
| 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 base backend in caching layers and returns a
|
| @@ -29,6 +40,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, do we have an expiration configured?
|
| + exp := time.Duration(s.CacheExpirationSec) * time.Second
|
| + if exp > 0 {
|
| + // The cache enabled enable. Install it into our backend.
|
| + locker := &dsCacheLocker{}
|
| + dsCfg := datastore.Config{
|
| + RefreshInterval: exp,
|
| + FailOpen: s.DatastoreCacheMode == gaeconfig.DSCacheEnabled,
|
| + LockerFunc: func(context.Context) datastorecache.Locker { return locker },
|
| + }
|
| + be = dsCfg.Backend(be)
|
| + }
|
| + }
|
| +
|
| + default:
|
| + log.WithError(err).Warningf(c, "Failed to fetch datastore cache settings.")
|
| + }
|
| + }
|
| +
|
| // Add a proccache-based config cache.
|
| if o.CacheExpiration > 0 {
|
| be = caching.ProcCache(be, o.CacheExpiration)
|
| @@ -37,3 +75,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
|
| +}
|
|
|