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

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

Issue 2575383002: Add server/cache support to gaeconfig. (Closed)
Patch Set: Un-collapse. Created 3 years, 11 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 unified diff | Download patch
« no previous file with comments | « appengine/gaeconfig/doc.go ('k') | appengine/gaemiddleware/context.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package gaeconfig
6
7 import (
8 "errors"
9 "fmt"
10 "net/url"
11 "strconv"
12 "time"
13
14 "golang.org/x/net/context"
15
16 "github.com/luci/luci-go/server/settings"
17 )
18
19 // DefaultExpire is a reasonable default expiration value.
20 const DefaultExpire = 10 * time.Minute
21
22 // Settings are stored in the datastore via appengine/gaesettings package.
23 type Settings struct {
24 // ConfigServiceURL is URL of luci-config service to fetch configs from.
25 ConfigServiceURL string `json:"config_service_url"`
26
27 // CacheExpirationSec is how long to hold configs in local cache.
28 CacheExpirationSec int `json:"cache_expiration_sec"`
29 }
30
31 // FetchCachedSettings fetches Settings from the settings store.
32 //
33 // Uses in-process global cache to avoid hitting datastore often. The cache
34 // expiration time is 1 min (see gaesettings.expirationTime), meaning
35 // the instance will refetch settings once a minute (blocking only one unlucky
36 // request to do so).
37 //
38 // 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.
40 func FetchCachedSettings(c context.Context) (Settings, error) {
41 s := Settings{}
42 switch err := settings.Get(c, settingsKey, &s); err {
43 case nil:
44 return s, nil
45 case settings.ErrNoSettings:
46 return DefaultSettings(), nil
47 default:
48 return Settings{}, err
49 }
50 }
51
52 // DefaultSettings returns Settings to use if setting store is empty.
53 func DefaultSettings() Settings {
54 return Settings{
55 CacheExpirationSec: int(DefaultExpire.Seconds()),
56 }
57 }
58
59 ////////////////////////////////////////////////////////////////////////////////
60 // UI for settings.
61
62 // settingsKey is used internally to identify gaeconfig settings in settings
63 // store.
64 const settingsKey = "gaeconfig"
65
66 type settingsUIPage struct {
67 settings.BaseUIPage
68 }
69
70 func (settingsUIPage) Title(c context.Context) (string, error) {
71 return "Configuration service settings", nil
72 }
73
74 func (settingsUIPage) Fields(c context.Context) ([]settings.UIField, error) {
75 return []settings.UIField{
76 {
77 ID: "ConfigServiceURL",
78 Title: "Config service URL",
79 Type: settings.UIFieldText,
80 Validator: func(v string) error {
81 if v != "" {
82 parsed, err := url.Parse(v)
83 if err != nil {
84 return fmt.Errorf("bad URL %q - %s", v, err)
85 }
86 if !parsed.IsAbs() || parsed.Path != "" {
87 return fmt.Errorf("bad URL %q - must be host root URL", v)
88 }
89 if parsed.Scheme != "https" {
90 return fmt.Errorf("bad URL %q - expecting https:// scheme", v)
91 }
92 }
93 return nil
94 },
95 Help: `<p>The application may fetch configuration files stored centrally
96 in an instance of <a href="https://github.com/luci/luci-py/tree/master/appengine /config_service">luci-config</a>
97 service. This is an URL of such service. If you don't know what this is, you
98 probably don't use it and can keep this setting blank.</p>`,
99 },
100 {
101 ID: "CacheExpirationSec",
102 Title: "Cache expiration, sec",
103 Type: settings.UIFieldText,
104 Validator: func(v string) error {
105 if i, err := strconv.Atoi(v); err != nil || i < 0 {
106 return errors.New("expecting a non-negat ive integer")
107 }
108 return nil
109 },
110 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
112 disable local cache.</p>`,
113 },
114 }, nil
115 }
116
117 func (settingsUIPage) ReadSettings(c context.Context) (map[string]string, error) {
118 s := DefaultSettings()
119 err := settings.GetUncached(c, settingsKey, &s)
120 if err != nil && err != settings.ErrNoSettings {
121 return nil, err
122 }
123 return map[string]string{
124 "ConfigServiceURL": s.ConfigServiceURL,
125 "CacheExpirationSec": strconv.Itoa(s.CacheExpirationSec),
126 }, nil
127 }
128
129 func (settingsUIPage) WriteSettings(c context.Context, values map[string]string, who, why string) error {
130 modified := Settings{}
131 modified.ConfigServiceURL = values["ConfigServiceURL"]
132
133 var err error
134 modified.CacheExpirationSec, err = strconv.Atoi(values["CacheExpirationS ec"])
135 if err != nil {
136 return err
137 }
138
139 return settings.SetIfChanged(c, settingsKey, &modified, who, why)
140 }
141
142 func init() {
143 settings.RegisterUIPage(settingsKey, settingsUIPage{})
144 }
OLDNEW
« no previous file with comments | « appengine/gaeconfig/doc.go ('k') | appengine/gaemiddleware/context.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698