Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package config | 5 package config |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "errors" | |
| 9 "fmt" | |
| 8 "time" | 10 "time" |
| 9 | 11 |
| 10 "github.com/golang/protobuf/proto" | 12 "github.com/golang/protobuf/proto" |
| 11 "github.com/luci/luci-go/common/clock" | 13 "github.com/luci/luci-go/common/clock" |
| 12 "github.com/luci/luci-go/common/config" | 14 "github.com/luci/luci-go/common/config" |
| 13 log "github.com/luci/luci-go/common/logging" | 15 log "github.com/luci/luci-go/common/logging" |
| 14 "github.com/luci/luci-go/common/proto/logdog/svcconfig" | 16 "github.com/luci/luci-go/common/proto/logdog/svcconfig" |
| 17 "github.com/luci/luci-go/server/proccache" | |
| 15 "golang.org/x/net/context" | 18 "golang.org/x/net/context" |
| 16 ) | 19 ) |
| 17 | 20 |
| 18 // Options is the set of options used to set up a Manager. | 21 // Options is the set of options used to set up a Manager. |
| 19 // | 22 // |
| 20 // The configuration is loaded from a svcconfig.Config protobuf. | 23 // The configuration is loaded from a svcconfig.Config protobuf. |
| 21 type Options struct { | 24 type Options struct { |
| 22 // Config is the configuration service to load from. | 25 // Config is the configuration service to load from. |
| 23 Config config.Interface | 26 Config config.Interface |
| 24 | 27 |
| 28 // ProjectID is the project's application ID. This is used to load | |
| 29 // project-specific configurations. | |
| 30 // | |
| 31 // If empty, project-specific configurations cannot be loaded. | |
| 32 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
| |
| 33 | |
| 25 // ConfigSet is the name of the ConfigSet to load. | 34 // ConfigSet is the name of the ConfigSet to load. |
| 26 ConfigSet string | 35 ConfigSet string |
| 27 // ServiceConfigPath is the name of the LogDog service config within the | 36 // ServiceConfigPath is the name of the LogDog service config within the |
| 28 // ConfigSet. | 37 // ConfigSet. |
| 29 ServiceConfigPath string | 38 ServiceConfigPath string |
| 30 | 39 |
| 40 // ProjectConfigCacheDuration is the amount of time to cache a project's | |
| 41 // configuration. If this is <= 0, the project config will be fetched ea ch | |
| 42 // time it's requested. | |
| 43 ProjectConfigCacheDuration time.Duration | |
| 44 | |
| 31 // KillCheckInterval, if >0, starts a goroutine that polls every interva l to | 45 // KillCheckInterval, if >0, starts a goroutine that polls every interva l to |
| 32 // see if the configuration has changed. If it has, KillFunc will be inv oked. | 46 // see if the configuration has changed. If it has, KillFunc will be inv oked. |
| 33 KillCheckInterval time.Duration | 47 KillCheckInterval time.Duration |
| 34 // KillFunc is the function that will be called if a configuration hash change | 48 // KillFunc is the function that will be called if a configuration hash change |
| 35 // has been observed. | 49 // has been observed. |
| 36 KillFunc func() | 50 KillFunc func() |
| 37 } | 51 } |
| 38 | 52 |
| 39 func (o *Options) getConfig(hashOnly bool) (*config.Config, error) { | 53 func (o *Options) getConfig(hashOnly bool) (*config.Config, error) { |
| 40 return o.Config.GetConfig(o.ConfigSet, o.ServiceConfigPath, hashOnly) | 54 return o.Config.GetConfig(o.ConfigSet, o.ServiceConfigPath, hashOnly) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 // It can also periodically refresh that configuration and invoke a shutdown | 98 // It can also periodically refresh that configuration and invoke a shutdown |
| 85 // function if its content changes. | 99 // function if its content changes. |
| 86 type Manager struct { | 100 type Manager struct { |
| 87 o *Options | 101 o *Options |
| 88 | 102 |
| 89 // cfg is the initial configuration. | 103 // cfg is the initial configuration. |
| 90 cfg svcconfig.Config | 104 cfg svcconfig.Config |
| 91 // cfgHash is the hash string of the original config. | 105 // cfgHash is the hash string of the original config. |
| 92 cfgHash string | 106 cfgHash string |
| 93 | 107 |
| 108 // projectConfigCache is a cache of project-specific configs. They will | |
| 109 // eventually timeout and get refreshed according to options. | |
| 110 projectConfigCache proccache.Cache | |
| 111 | |
| 94 // configChangedC will contain the result of the most recent configurati on | 112 // configChangedC will contain the result of the most recent configurati on |
| 95 // change poll operation. The configuration change poller will block unt il | 113 // change poll operation. The configuration change poller will block unt il |
| 96 // that result is consumed. | 114 // that result is consumed. |
| 97 configChangedC chan struct{} | 115 configChangedC chan struct{} |
| 98 // changePollerCancelFunc is the cancel function to call to stop the | 116 // changePollerCancelFunc is the cancel function to call to stop the |
| 99 // configuration poller. | 117 // configuration poller. |
| 100 changePollerCancelFunc func() | 118 changePollerCancelFunc func() |
| 101 } | 119 } |
| 102 | 120 |
| 103 // NewManager generates a new Manager and loads the initial configuration. | 121 // NewManager generates a new Manager and loads the initial configuration. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 123 } | 141 } |
| 124 | 142 |
| 125 return &m, nil | 143 return &m, nil |
| 126 } | 144 } |
| 127 | 145 |
| 128 // Config returns the service configuration instance. | 146 // Config returns the service configuration instance. |
| 129 func (m *Manager) Config() *svcconfig.Config { | 147 func (m *Manager) Config() *svcconfig.Config { |
| 130 return &m.cfg | 148 return &m.cfg |
| 131 } | 149 } |
| 132 | 150 |
| 151 // ProjectConfig returns the project configuration. | |
| 152 func (m *Manager) ProjectConfig(c context.Context, project config.ProjectName) ( *svcconfig.ProjectConfig, error) { | |
| 153 projectID := m.o.ProjectID | |
|
nodir
2016/05/18 16:25:51
This is app id
dnj (Google)
2016/05/18 16:50:31
Acknowledged.
| |
| 154 if projectID == "" { | |
| 155 return nil, errors.New("no app ID specified") | |
| 156 } | |
| 157 | |
| 158 v, err := proccache.GetOrMake(c, project, func() (interface{}, time.Dura tion, error) { | |
| 159 configSet := fmt.Sprintf("projects/%s", project) | |
| 160 configPath := fmt.Sprintf("%s.cfg", projectID) | |
| 161 cfg, err := m.o.Config.GetConfig(configSet, configPath, false) | |
| 162 if err != nil { | |
| 163 log.Fields{ | |
| 164 log.ErrorKey: err, | |
| 165 "project": project, | |
| 166 }.Errorf(c, "Failed to load config.") | |
| 167 return nil, 0, err | |
| 168 } | |
| 169 | |
| 170 var pcfg svcconfig.ProjectConfig | |
| 171 if err := proto.UnmarshalText(cfg.Content, &pcfg); err != nil { | |
| 172 log.Fields{ | |
| 173 log.ErrorKey: err, | |
| 174 "project": project, | |
| 175 "hash": cfg.ContentHash, | |
| 176 "configSet": configSet, | |
| 177 "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
| |
| 178 }.Errorf(c, "Failed to unmarshal project config.") | |
| 179 } | |
| 180 | |
| 181 log.Fields{ | |
| 182 "cacheDuration": m.o.ProjectConfigCacheDuration, | |
| 183 "project": project, | |
| 184 "hash": cfg.ContentHash, | |
| 185 "configSet": configSet, | |
| 186 "path": configPath, | |
|
nodir
2016/05/18 16:25:51
Sort?
dnj (Google)
2016/05/18 16:50:31
Acknowledged.
| |
| 187 }.Infof(c, "Refreshed project configuration.") | |
| 188 return &pcfg, m.o.ProjectConfigCacheDuration, nil | |
| 189 }) | |
| 190 if err != nil { | |
| 191 return nil, err | |
| 192 } | |
| 193 return v.(*svcconfig.ProjectConfig), nil | |
| 194 } | |
| 195 | |
| 133 // Close terminates the config change poller and blocks until it has finished. | 196 // Close terminates the config change poller and blocks until it has finished. |
| 134 // | 197 // |
| 135 // Close must be called in order to ensure that Go scheduler properly schedules | 198 // Close must be called in order to ensure that Go scheduler properly schedules |
| 136 // the goroutine. | 199 // the goroutine. |
| 137 func (m *Manager) Close() { | 200 func (m *Manager) Close() { |
| 138 // If our config change poller is running, cancel and reap it. | 201 // If our config change poller is running, cancel and reap it. |
| 139 if m.changePollerCancelFunc != nil { | 202 if m.changePollerCancelFunc != nil { |
| 140 m.changePollerCancelFunc() | 203 m.changePollerCancelFunc() |
| 141 <-m.configChangedC | 204 <-m.configChangedC |
| 142 } | 205 } |
| 143 } | 206 } |
| 144 | 207 |
| 145 func (m *Manager) reloadConfig(c context.Context) error { | 208 func (m *Manager) reloadConfig(c context.Context) error { |
| 146 cfg, err := m.o.getConfig(false) | 209 cfg, err := m.o.getConfig(false) |
| 147 if err != nil { | 210 if err != nil { |
| 148 return err | 211 return err |
| 149 } | 212 } |
| 150 | 213 |
| 151 if err := proto.UnmarshalText(cfg.Content, &m.cfg); err != nil { | 214 if err := proto.UnmarshalText(cfg.Content, &m.cfg); err != nil { |
| 152 log.Fields{ | 215 log.Fields{ |
| 153 log.ErrorKey: err, | 216 log.ErrorKey: err, |
| 154 "hash": cfg.ContentHash, | 217 "hash": cfg.ContentHash, |
| 155 }.Errorf(c, "Failed to unmarshal configuration.") | 218 }.Errorf(c, "Failed to unmarshal configuration.") |
| 156 return err | 219 return err |
| 157 } | 220 } |
| 158 m.cfgHash = cfg.ContentHash | 221 m.cfgHash = cfg.ContentHash |
| 159 return nil | 222 return nil |
| 160 } | 223 } |
| OLD | NEW |