Index: server/internal/logdog/service/config/config.go |
diff --git a/server/internal/logdog/service/config/config.go b/server/internal/logdog/service/config/config.go |
index 6fed7b09ce6fb62617593b884e9d935c6f706f59..37dacd0dffdf0f8998f6c76d285d9b2d71ce7ec5 100644 |
--- a/server/internal/logdog/service/config/config.go |
+++ b/server/internal/logdog/service/config/config.go |
@@ -5,6 +5,8 @@ |
package config |
import ( |
+ "errors" |
+ "fmt" |
"time" |
"github.com/golang/protobuf/proto" |
@@ -12,6 +14,7 @@ import ( |
"github.com/luci/luci-go/common/config" |
log "github.com/luci/luci-go/common/logging" |
"github.com/luci/luci-go/common/proto/logdog/svcconfig" |
+ "github.com/luci/luci-go/server/proccache" |
"golang.org/x/net/context" |
) |
@@ -22,12 +25,23 @@ type Options struct { |
// Config is the configuration service to load from. |
Config config.Interface |
+ // ProjectID is the project's application ID. This is used to load |
+ // project-specific configurations. |
+ // |
+ // If empty, project-specific configurations cannot be loaded. |
+ ProjectID string |
nodir
2016/05/18 16:25:51
Better call it AppID so it is unambiguous. Luci co
dnj (Google)
2016/05/18 16:50:31
I'm using the term, "project ID", here, which is c
nodir
2016/05/18 17:02:19
I don't understand. This is app id, see how is it
|
+ |
// ConfigSet is the name of the ConfigSet to load. |
ConfigSet string |
// ServiceConfigPath is the name of the LogDog service config within the |
// ConfigSet. |
ServiceConfigPath string |
+ // ProjectConfigCacheDuration is the amount of time to cache a project's |
+ // configuration. If this is <= 0, the project config will be fetched each |
+ // time it's requested. |
+ ProjectConfigCacheDuration time.Duration |
+ |
// KillCheckInterval, if >0, starts a goroutine that polls every interval to |
// see if the configuration has changed. If it has, KillFunc will be invoked. |
KillCheckInterval time.Duration |
@@ -91,6 +105,10 @@ type Manager struct { |
// cfgHash is the hash string of the original config. |
cfgHash string |
+ // projectConfigCache is a cache of project-specific configs. They will |
+ // eventually timeout and get refreshed according to options. |
+ projectConfigCache proccache.Cache |
+ |
// configChangedC will contain the result of the most recent configuration |
// change poll operation. The configuration change poller will block until |
// that result is consumed. |
@@ -130,6 +148,51 @@ func (m *Manager) Config() *svcconfig.Config { |
return &m.cfg |
} |
+// ProjectConfig returns the project configuration. |
+func (m *Manager) ProjectConfig(c context.Context, project config.ProjectName) (*svcconfig.ProjectConfig, error) { |
+ projectID := m.o.ProjectID |
nodir
2016/05/18 16:25:51
This is app id
dnj (Google)
2016/05/18 16:50:31
Acknowledged.
|
+ if projectID == "" { |
+ return nil, errors.New("no app ID specified") |
+ } |
+ |
+ v, err := proccache.GetOrMake(c, project, func() (interface{}, time.Duration, error) { |
+ configSet := fmt.Sprintf("projects/%s", project) |
+ configPath := fmt.Sprintf("%s.cfg", projectID) |
+ cfg, err := m.o.Config.GetConfig(configSet, configPath, false) |
+ if err != nil { |
+ log.Fields{ |
+ log.ErrorKey: err, |
+ "project": project, |
+ }.Errorf(c, "Failed to load config.") |
+ return nil, 0, err |
+ } |
+ |
+ var pcfg svcconfig.ProjectConfig |
+ if err := proto.UnmarshalText(cfg.Content, &pcfg); err != nil { |
+ log.Fields{ |
+ log.ErrorKey: err, |
+ "project": project, |
+ "hash": cfg.ContentHash, |
+ "configSet": configSet, |
+ "path": configPath, |
nodir
2016/05/18 16:25:51
Sort?
dnj (Google)
2016/05/18 16:50:31
I don't think you need to pay so much attention to
|
+ }.Errorf(c, "Failed to unmarshal project config.") |
+ } |
+ |
+ log.Fields{ |
+ "cacheDuration": m.o.ProjectConfigCacheDuration, |
+ "project": project, |
+ "hash": cfg.ContentHash, |
+ "configSet": configSet, |
+ "path": configPath, |
nodir
2016/05/18 16:25:51
Sort?
dnj (Google)
2016/05/18 16:50:31
Acknowledged.
|
+ }.Infof(c, "Refreshed project configuration.") |
+ return &pcfg, m.o.ProjectConfigCacheDuration, nil |
+ }) |
+ if err != nil { |
+ return nil, err |
+ } |
+ return v.(*svcconfig.ProjectConfig), nil |
+} |
+ |
// Close terminates the config change poller and blocks until it has finished. |
// |
// Close must be called in order to ensure that Go scheduler properly schedules |