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

Side by Side Diff: appengine/gaeconfig/settings.go

Issue 2575383002: Add server/cache support to gaeconfig. (Closed)
Patch Set: Created 4 years 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The LUCI Authors. All rights reserved. 1 // Copyright 2016 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 gaeconfig 5 package gaeconfig
6 6
7 import ( 7 import (
8 "errors" 8 "errors"
9 "fmt" 9 "fmt"
10 "net/url" 10 "net/url"
11 "strconv" 11 "strconv"
12 "time" 12 "time"
13 13
14 "golang.org/x/net/context" 14 "golang.org/x/net/context"
15 15
16 "github.com/luci/luci-go/server/settings" 16 "github.com/luci/luci-go/server/settings"
17 ) 17 )
18 18
19 // DefaultExpire is a reasonable default expiration value. 19 // DefaultExpire is a reasonable default expiration value.
20 const DefaultExpire = 10 * time.Minute 20 const DefaultExpire = 10 * time.Minute
21 21
22 type dsCacheMode string
23
24 const (
25 dsCacheDisabled dsCacheMode = ""
26 dsCacheEnabled dsCacheMode = "Enabled"
27 dsCacheStrict dsCacheMode = "Strict"
28 )
29
30 const dsCacheDisabledSetting = "Disabled"
31
22 // Settings are stored in the datastore via appengine/gaesettings package. 32 // Settings are stored in the datastore via appengine/gaesettings package.
23 type Settings struct { 33 type Settings struct {
24 // ConfigServiceURL is URL of luci-config service to fetch configs from. 34 // ConfigServiceURL is URL of luci-config service to fetch configs from.
25 ConfigServiceURL string `json:"config_service_url"` 35 ConfigServiceURL string `json:"config_service_url"`
26 36
27 // CacheExpirationSec is how long to hold configs in local cache. 37 // CacheExpirationSec is how long to hold configs in local cache.
28 CacheExpirationSec int `json:"cache_expiration_sec"` 38 CacheExpirationSec int `json:"cache_expiration_sec"`
39
40 // DatastoreCacheMode, is the datastore caching mode.
41 DatastoreCacheMode dsCacheMode `json:"datastore_enabled"`
29 } 42 }
30 43
31 // FetchCachedSettings fetches Settings from the settings store. 44 // FetchCachedSettings fetches Settings from the settings store.
32 // 45 //
33 // Uses in-process global cache to avoid hitting datastore often. The cache 46 // Uses in-process global cache to avoid hitting datastore often. The cache
34 // expiration time is 1 min (see gaesettings.expirationTime), meaning 47 // expiration time is 1 min (see gaesettings.expirationTime), meaning
35 // the instance will refetch settings once a minute (blocking only one unlucky 48 // the instance will refetch settings once a minute (blocking only one unlucky
36 // request to do so). 49 // request to do so).
37 // 50 //
38 // Returns errors only if there's no cached value (i.e. it is the first call 51 // Returns errors only if there's no cached value (i.e. it is the first call
39 // to this function in this process ever) and datastore operation fails. 52 // to this function in this process ever) and datastore operation fails.
40 func FetchCachedSettings(c context.Context) (Settings, error) { 53 func FetchCachedSettings(c context.Context) (Settings, error) {
41 s := Settings{} 54 s := Settings{}
42 switch err := settings.Get(c, settingsKey, &s); err { 55 switch err := settings.Get(c, settingsKey, &s); err {
43 case nil: 56 case nil:
44 return s, nil 57 return s, nil
45 case settings.ErrNoSettings: 58 case settings.ErrNoSettings:
46 return DefaultSettings(), nil 59 return DefaultSettings(), nil
47 default: 60 default:
48 return Settings{}, err 61 return Settings{}, err
49 } 62 }
50 } 63 }
51 64
65 func mustFetchCachedSettings(c context.Context) *Settings {
66 settings, err := FetchCachedSettings(c)
67 if err != nil {
68 panic(err)
69 }
70 return &settings
71 }
72
52 // DefaultSettings returns Settings to use if setting store is empty. 73 // DefaultSettings returns Settings to use if setting store is empty.
53 func DefaultSettings() Settings { 74 func DefaultSettings() Settings {
54 return Settings{ 75 return Settings{
55 CacheExpirationSec: int(DefaultExpire.Seconds()), 76 CacheExpirationSec: int(DefaultExpire.Seconds()),
77 DatastoreCacheMode: dsCacheDisabled,
56 } 78 }
57 } 79 }
58 80
59 //////////////////////////////////////////////////////////////////////////////// 81 ////////////////////////////////////////////////////////////////////////////////
60 // UI for settings. 82 // UI for settings.
61 83
62 // settingsKey is used internally to identify gaeconfig settings in settings 84 // settingsKey is used internally to identify gaeconfig settings in settings
63 // store. 85 // store.
64 const settingsKey = "gaeconfig" 86 const settingsKey = "gaeconfig"
65 87
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 Validator: func(v string) error { 126 Validator: func(v string) error {
105 if i, err := strconv.Atoi(v); err != nil || i < 0 { 127 if i, err := strconv.Atoi(v); err != nil || i < 0 {
106 return errors.New("expecting a non-negat ive integer") 128 return errors.New("expecting a non-negat ive integer")
107 } 129 }
108 return nil 130 return nil
109 }, 131 },
110 Help: `<p>For better performance configuration files fet ched from remote 132 Help: `<p>For better performance configuration files fet ched from remote
111 service are cached in memcache for specified amount of time. Set it to 0 to 133 service are cached in memcache for specified amount of time. Set it to 0 to
112 disable local cache.</p>`, 134 disable local cache.</p>`,
113 }, 135 },
136 {
137 ID: "DatastoreCacheMode",
138 Title: "Enable datastore-backed config caching",
139 Type: settings.UIFieldChoice,
140 ChoiceVariants: []string{
141 dsCacheDisabledSetting,
142 string(dsCacheEnabled),
143 string(dsCacheStrict),
144 },
145 Help: `<p>For better performance and resilience against configuration
146 service outages, the local datastore can be used as a backing cache. When
147 enabled, an additional <strong>Strict</strong> mode is available where expired
148 datastore entries will error instead of fail-open to the config service.</p>`,
149 },
114 }, nil 150 }, nil
115 } 151 }
116 152
117 func (settingsUIPage) ReadSettings(c context.Context) (map[string]string, error) { 153 func (settingsUIPage) ReadSettings(c context.Context) (map[string]string, error) {
118 s := DefaultSettings() 154 s := DefaultSettings()
119 err := settings.GetUncached(c, settingsKey, &s) 155 err := settings.GetUncached(c, settingsKey, &s)
120 if err != nil && err != settings.ErrNoSettings { 156 if err != nil && err != settings.ErrNoSettings {
121 return nil, err 157 return nil, err
122 } 158 }
159
160 cacheMode := string(s.DatastoreCacheMode)
161 if cacheMode == string(dsCacheDisabled) {
162 cacheMode = dsCacheDisabledSetting
163 }
164
123 return map[string]string{ 165 return map[string]string{
124 "ConfigServiceURL": s.ConfigServiceURL, 166 "ConfigServiceURL": s.ConfigServiceURL,
125 "CacheExpirationSec": strconv.Itoa(s.CacheExpirationSec), 167 "CacheExpirationSec": strconv.Itoa(s.CacheExpirationSec),
168 "DatastoreCacheMode": cacheMode,
126 }, nil 169 }, nil
127 } 170 }
128 171
129 func (settingsUIPage) WriteSettings(c context.Context, values map[string]string, who, why string) error { 172 func (settingsUIPage) WriteSettings(c context.Context, values map[string]string, who, why string) error {
130 » modified := Settings{} 173 » dsMode := dsCacheMode(values["DatastoreCacheMode"])
131 » modified.ConfigServiceURL = values["ConfigServiceURL"] 174 » if dsMode == dsCacheDisabledSetting {
175 » » dsMode = dsCacheDisabled
176 » }
177
178 » modified := Settings{
179 » » ConfigServiceURL: values["ConfigServiceURL"],
180 » » DatastoreCacheMode: dsMode,
181 » }
132 182
133 var err error 183 var err error
134 modified.CacheExpirationSec, err = strconv.Atoi(values["CacheExpirationS ec"]) 184 modified.CacheExpirationSec, err = strconv.Atoi(values["CacheExpirationS ec"])
135 if err != nil { 185 if err != nil {
136 return err 186 return err
137 } 187 }
138 188
139 return settings.SetIfChanged(c, settingsKey, &modified, who, why) 189 return settings.SetIfChanged(c, settingsKey, &modified, who, why)
140 } 190 }
141 191
142 func init() { 192 func init() {
143 settings.RegisterUIPage(settingsKey, settingsUIPage{}) 193 settings.RegisterUIPage(settingsKey, settingsUIPage{})
144 } 194 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698