| OLD | NEW |
| 1 // Copyright 2017 The LUCI Authors. All rights reserved. | 1 // Copyright 2017 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package config | 5 package config |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "time" | 8 "time" |
| 9 | 9 |
| 10 "github.com/luci/luci-go/appengine/datastorecache" |
| 11 log "github.com/luci/luci-go/common/logging" |
| 12 "github.com/luci/luci-go/common/sync/mutexpool" |
| 13 "github.com/luci/luci-go/luci_config/appengine/backend/datastore" |
| 14 "github.com/luci/luci-go/luci_config/appengine/gaeconfig" |
| 10 "github.com/luci/luci-go/luci_config/server/cfgclient/backend" | 15 "github.com/luci/luci-go/luci_config/server/cfgclient/backend" |
| 11 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/caching" | 16 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/caching" |
| 12 | 17 |
| 13 "golang.org/x/net/context" | 18 "golang.org/x/net/context" |
| 14 ) | 19 ) |
| 15 | 20 |
| 16 // CacheOptions is the set of configuration options. | 21 // CacheOptions is the set of configuration options. |
| 17 type CacheOptions struct { | 22 type CacheOptions struct { |
| 18 // CacheExpiration is the amount of time that a config entry should be c
ached. | 23 // CacheExpiration is the amount of time that a config entry should be c
ached. |
| 19 // | 24 // |
| 20 // If this value is <= 0, no configuration caching will be enabled. This | 25 // If this value is <= 0, no configuration caching will be enabled. This |
| 21 // should not be set for production systems. | 26 // should not be set for production systems. |
| 22 CacheExpiration time.Duration | 27 CacheExpiration time.Duration |
| 28 |
| 29 // DatastoreCacheAvailable, if true, indicates that requisite services f
or |
| 30 // datastore cache access are installed in the Context. This requires: |
| 31 // - A luci/gae datastore service instnace |
| 32 // - A settings service instance, presumably gaesettings. |
| 33 DatastoreCacheAvailable bool |
| 23 } | 34 } |
| 24 | 35 |
| 25 // WrapBackend wraps the supplied base backend in caching layers and returns a | 36 // WrapBackend wraps the supplied base backend in caching layers and returns a |
| 26 // Conext with the resulting backend installed. | 37 // Conext with the resulting backend installed. |
| 27 func (o *CacheOptions) WrapBackend(c context.Context, base backend.B) context.Co
ntext { | 38 func (o *CacheOptions) WrapBackend(c context.Context, base backend.B) context.Co
ntext { |
| 28 return backend.WithFactory(c, func(c context.Context) backend.B { | 39 return backend.WithFactory(c, func(c context.Context) backend.B { |
| 29 // Start with our base Backend. | 40 // Start with our base Backend. |
| 30 be := base | 41 be := base |
| 31 | 42 |
| 43 // If our datastore cache is available, fetch settings to see if
it's |
| 44 // enabled. |
| 45 if o.DatastoreCacheAvailable { |
| 46 switch s, err := gaeconfig.FetchCachedSettings(c); err { |
| 47 case nil: |
| 48 // Successfully fetched settings, is our datasto
re cache enabled? |
| 49 switch s.DatastoreCacheMode { |
| 50 case gaeconfig.DSCacheEnabled, gaeconfig.DSCache
Strict: |
| 51 // Datastore cache is enabled, do we hav
e an expiration configured? |
| 52 exp := time.Duration(s.CacheExpirationSe
c) * time.Second |
| 53 if exp > 0 { |
| 54 // The cache enabled enable. Ins
tall it into our backend. |
| 55 locker := &dsCacheLocker{} |
| 56 dsCfg := datastore.Config{ |
| 57 RefreshInterval: exp, |
| 58 FailOpen: s.Datas
toreCacheMode == gaeconfig.DSCacheEnabled, |
| 59 LockerFunc: func(co
ntext.Context) datastorecache.Locker { return locker }, |
| 60 } |
| 61 be = dsCfg.Backend(be) |
| 62 } |
| 63 } |
| 64 |
| 65 default: |
| 66 log.WithError(err).Warningf(c, "Failed to fetch
datastore cache settings.") |
| 67 } |
| 68 } |
| 69 |
| 32 // Add a proccache-based config cache. | 70 // Add a proccache-based config cache. |
| 33 if o.CacheExpiration > 0 { | 71 if o.CacheExpiration > 0 { |
| 34 be = caching.ProcCache(be, o.CacheExpiration) | 72 be = caching.ProcCache(be, o.CacheExpiration) |
| 35 } | 73 } |
| 36 | 74 |
| 37 return be | 75 return be |
| 38 }) | 76 }) |
| 39 } | 77 } |
| 78 |
| 79 type dsCacheLocker struct { |
| 80 p mutexpool.P |
| 81 } |
| 82 |
| 83 func (l *dsCacheLocker) TryWithLock(c context.Context, key string, fn func(conte
xt.Context) error) (err error) { |
| 84 l.p.WithMutex(key, func() { |
| 85 err = fn(c) |
| 86 }) |
| 87 return |
| 88 } |
| OLD | NEW |