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

Unified Diff: appengine/logdog/coordinator/service.go

Issue 1971623002: LogDog: Enable Coordinator to load project configs (Closed) Base URL: https://github.com/luci/luci-go@logdog-project-config
Patch Set: Created 4 years, 7 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: appengine/logdog/coordinator/service.go
diff --git a/appengine/logdog/coordinator/service.go b/appengine/logdog/coordinator/service.go
index 10f04358791cb8a02016bfe7417051da49b5c958..2e839735630a962294dff44ff085377b69babc2d 100644
--- a/appengine/logdog/coordinator/service.go
+++ b/appengine/logdog/coordinator/service.go
@@ -12,10 +12,12 @@ import (
"github.com/julienschmidt/httprouter"
gaeauthClient "github.com/luci/luci-go/appengine/gaeauth/client"
"github.com/luci/luci-go/appengine/logdog/coordinator/config"
+ luciConfig "github.com/luci/luci-go/common/config"
"github.com/luci/luci-go/common/errors"
"github.com/luci/luci-go/common/gcloud/gs"
"github.com/luci/luci-go/common/gcloud/pubsub"
log "github.com/luci/luci-go/common/logging"
+ "github.com/luci/luci-go/common/proto/logdog/svcconfig"
"github.com/luci/luci-go/server/logdog/storage"
"github.com/luci/luci-go/server/logdog/storage/bigtable"
"github.com/luci/luci-go/server/middleware"
@@ -43,6 +45,12 @@ type Services interface {
// request.
Config(context.Context) (*config.Config, error)
+ // ProjectConfig returns the project configuration for the named project.
+ //
+ // The production instance will cache the results for the duration of the
+ // request.
+ ProjectConfig(context.Context, luciConfig.ProjectName) (*svcconfig.ProjectConfig, error)
+
// Storage returns an intermediate storage instance for use by this service.
//
// The caller must close the returned instance if successful.
@@ -76,7 +84,8 @@ type prodServicesInst struct {
sync.Mutex
// gcfg is the cached global configuration.
- gcfg *config.Config
+ gcfg *config.Config
+ projectConfigs map[luciConfig.ProjectName]*cachedProjectConfig
// archivalIndex is the atomically-manipulated archival index for the
// ArchivalPublisher. This is shared between all ArchivalPublisher instances
@@ -84,9 +93,6 @@ type prodServicesInst struct {
archivalIndex int32
}
-// Config returns the current instance and application configuration instances.
-//
-// After a success, successive calls will return a cached result.
func (s *prodServicesInst) Config(c context.Context) (*config.Config, error) {
s.Lock()
defer s.Unlock()
@@ -103,6 +109,50 @@ func (s *prodServicesInst) Config(c context.Context) (*config.Config, error) {
return s.gcfg, nil
}
+// cachedProjectConfig is a singleton instance that holds a project config
+// state. It is populated when resolve is called, and is goroutine-safe for
+// read-only operations.
+type cachedProjectConfig struct {
+ sync.Once
+
+ project luciConfig.ProjectName
+ pcfg *svcconfig.ProjectConfig
+ err error
+}
+
+func (cp *cachedProjectConfig) resolve(c context.Context) (*svcconfig.ProjectConfig, error) {
+ // Load the project config exactly once. This will be cached for the remainder
+ // of this request.
+ //
+ // If multiple goroutines attempt to load it, exactly one will, and the rest
+ // will block. All operations after this Once must be read-only.
+ cp.Do(func() {
+ cp.pcfg, cp.err = config.ProjectConfig(c, cp.project)
+ })
+ return cp.pcfg, cp.err
+}
+
+func (s *prodServicesInst) getOrCreateCachedProjectConfig(project luciConfig.ProjectName) *cachedProjectConfig {
+ s.Lock()
+ defer s.Unlock()
+
+ if s.projectConfigs == nil {
+ s.projectConfigs = make(map[luciConfig.ProjectName]*cachedProjectConfig)
+ }
+ cp := s.projectConfigs[project]
+ if cp == nil {
+ cp = &cachedProjectConfig{
+ project: project,
+ }
+ s.projectConfigs[project] = cp
+ }
+ return cp
+}
+
+func (s *prodServicesInst) ProjectConfig(c context.Context, project luciConfig.ProjectName) (*svcconfig.ProjectConfig, error) {
+ return s.getOrCreateCachedProjectConfig(project).resolve(c)
+}
+
func (s *prodServicesInst) IntermediateStorage(c context.Context) (storage.Storage, error) {
cfg, err := s.Config(c)
if err != nil {

Powered by Google App Engine
This is Rietveld 408576698