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

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

Issue 2576923003: Implement config service cache on top of datastore (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 "os" 10 "os"
11 "path/filepath" 11 "path/filepath"
12 "time" 12 "time"
13 13
14 "github.com/luci/luci-go/common/config/impl/filesystem" 14 "github.com/luci/luci-go/common/config/impl/filesystem"
15 "github.com/luci/luci-go/server/config" 15 "github.com/luci/luci-go/server/config"
16 "github.com/luci/luci-go/server/config/caching" 16 "github.com/luci/luci-go/server/config/caching"
17 "github.com/luci/luci-go/server/config/erroring" 17 "github.com/luci/luci-go/server/config/erroring"
18 "github.com/luci/luci-go/server/config/testconfig" 18 "github.com/luci/luci-go/server/config/testconfig"
19 "github.com/luci/luci-go/server/config/textproto" 19 "github.com/luci/luci-go/server/config/textproto"
20 "github.com/luci/luci-go/server/router"
20 21
21 "github.com/luci/gae/service/info" 22 "github.com/luci/gae/service/info"
22 23
23 "golang.org/x/net/context" 24 "golang.org/x/net/context"
24 ) 25 )
25 26
26 // ErrNotConfigured is returned by methods of config.Backend object returned 27 // ErrNotConfigured is returned by methods of config.Backend object returned
27 // by New if config service URL is not set. Usually happens for new apps. 28 // by New if config service URL is not set. Usually happens for new apps.
28 var ErrNotConfigured = errors.New("config service URL is not set in settings") 29 var ErrNotConfigured = errors.New("config service URL is not set in settings")
29 30
30 // devCfgDir is a name of the directory with config files when running in 31 // devCfgDir is a name of the directory with config files when running in
31 // local dev appserver model. See New for details. 32 // local dev appserver model. See New for details.
32 const devCfgDir = "devcfg" 33 const devCfgDir = "devcfg"
33 34
35 // InstallCacheCronHandler installs the configuration service datastore caching
36 // cron handler. This must be installed, and an associated cron must be set up,
37 // if datastore caching is enabled.
38 //
39 // The cron should be configured to hit the handler at:
40 // /admin/config/cache/manager
41 func InstallCacheCronHandler(r *router.Router, base router.MiddlewareChain) {
42 installCacheCronHandlerImpl(r, base, nil)
43 }
44
45 // Install our cache cron handler into the supplied Router.
46 //
47 // bf is a generator function used to get the primary (service) Backend to build
48 // on top of. If nil, the "production" (one used by Use) Backend will be used.
49 func installCacheCronHandlerImpl(r *router.Router, base router.MiddlewareChain, backend config.Backend) {
50 base = base.Extend(func(c *router.Context, next router.Handler) {
51 // Install our Backend into our Context.
52 c.Context = installConfigBackend(c.Context, mustFetchCachedSetti ngs(c.Context), backend, true)
53 next(c)
54 })
55
56 dsCache.InstallCronRoute("/admin/config/cache/manager", r, base)
57 }
58
34 // Use installs the default luci-config client. 59 // Use installs the default luci-config client.
35 // 60 //
36 // The client is configured to use luci-config URL specified in the settings, 61 // The client is configured to use luci-config URL specified in the settings,
37 // using GAE app service account for authentication. 62 // using GAE app service account for authentication.
38 // 63 //
39 // If running in prod, and the settings don't specify luci-config URL, produces 64 // If running in prod, and the settings don't specify luci-config URL, produces
40 // an implementation of config.Interface that returns ErrNotConfigured from all 65 // an implementation of config.Interface that returns ErrNotConfigured from all
41 // methods. 66 // methods.
42 // 67 //
43 // If running on devserver, and the settings don't specify luci-config URL, 68 // If running on devserver, and the settings don't specify luci-config URL,
44 // returns a filesystem-based implementation that reads configs from a directory 69 // returns a filesystem-based implementation that reads configs from a directory
45 // (or a symlink) named 'devcfg' located in the GAE module directory (where 70 // (or a symlink) named 'devcfg' located in the GAE module directory (where
46 // app.yaml is) or its immediate parent directory. 71 // app.yaml is) or its immediate parent directory.
47 // 72 //
48 // If such directory can not be located, produces an implementation of 73 // If such directory can not be located, produces an implementation of
49 // config.Interface that returns errors from all methods. 74 // config.Interface that returns errors from all methods.
50 // 75 //
51 // Panics if it can't load the settings (should not happen since they are in 76 // Panics if it can't load the settings (should not happen since they are in
52 // the local memory cache usually). 77 // the local memory cache usually).
53 func Use(c context.Context) context.Context { return useImpl(c, nil) } 78 func Use(c context.Context) context.Context { return useImpl(c, nil) }
54 79
55 func useImpl(c context.Context, backend config.Backend) context.Context { 80 func useImpl(c context.Context, backend config.Backend) context.Context {
56 » return installConfigBackend(c, mustFetchCachedSettings(c), backend) 81 » return installConfigBackend(c, mustFetchCachedSettings(c), backend, fals e)
57 } 82 }
58 83
59 func installConfigBackend(c context.Context, s *Settings, backend config.Backend ) context.Context { 84 func installConfigBackend(c context.Context, s *Settings, backend config.Backend , dsCron bool) context.Context {
60 if backend == nil { 85 if backend == nil {
61 // Non-testing, build a Backend. 86 // Non-testing, build a Backend.
62 backend = getPrimaryBackend(c, s) 87 backend = getPrimaryBackend(c, s)
63 } 88 }
64 89
65 // Install a FormatRegistry. Register common config service protobufs wi th it. 90 // Install a FormatRegistry. Register common config service protobufs wi th it.
66 c = withFormatRegistry(c, defaultFormatterRegistry()) 91 c = withFormatRegistry(c, defaultFormatterRegistry())
67 92
68 backend = &config.FormatBackend{ 93 backend = &config.FormatBackend{
69 Backend: backend, 94 Backend: backend,
70 GetRegistry: GetFormatterRegistry, 95 GetRegistry: GetFormatterRegistry,
71 } 96 }
72 97
73 // Apply caching configuration. 98 // Apply caching configuration.
74 exp := time.Duration(s.CacheExpirationSec) * time.Second 99 exp := time.Duration(s.CacheExpirationSec) * time.Second
75 if exp > 0 { 100 if exp > 0 {
76 // Add a ProcCache, backed by memcache. 101 // Add a ProcCache, backed by memcache.
77 backend = caching.ProcCache(backend, exp) 102 backend = caching.ProcCache(backend, exp)
78 backend = memcacheBackend(backend, exp) 103 backend = memcacheBackend(backend, exp)
104
105 // If our datastore cache is enabled, install a handler for refr esh. This
106 // will be loaded by dsCache's "HandlerFunc".
107 if s.DatastoreCacheMode != dsCacheDisabled {
108 dsc := datastoreCache{
109 refreshInterval: exp,
110 failOpen: s.DatastoreCacheMode == dsCache Enabled,
111 }
112
113 if !dsCron {
114 // For non-cron, install the datastore cache Bac kend.
115 backend = dsc.getBackend(backend)
116 } else {
117 // For cron, do not install the datastore cache Backend. Instead,
118 // install a lasting Handler into the Context to be used for cache
119 // resolution. This is necessary since resolutio n calls will not be
120 // the result of an actual resolution command (e .g., cache.Get).
121 c = dsc.withHandler(c, datastoreCronLoader(backe nd), dsRPCDeadline)
122 }
123 }
79 } 124 }
80 125
81 c = config.WithBackend(c, backend) 126 c = config.WithBackend(c, backend)
82 return c 127 return c
83 } 128 }
84 129
85 func getPrimaryBackend(c context.Context, settings *Settings) (backend config.Ba ckend) { 130 func getPrimaryBackend(c context.Context, settings *Settings) (backend config.Ba ckend) {
86 // Identify our config service Backend (in testing, it will be supplied) . 131 // Identify our config service Backend (in testing, it will be supplied) .
87 if settings.ConfigServiceURL == "" { 132 if settings.ConfigServiceURL == "" {
88 if info.IsDevAppServer(c) { 133 if info.IsDevAppServer(c) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 173
129 func withFormatRegistry(c context.Context, fr *config.FormatterRegistry) context .Context { 174 func withFormatRegistry(c context.Context, fr *config.FormatterRegistry) context .Context {
130 return context.WithValue(c, &formatRegistryKey, fr) 175 return context.WithValue(c, &formatRegistryKey, fr)
131 } 176 }
132 177
133 // GetFormatterRegistry is used to retrieve the config service format registry 178 // GetFormatterRegistry is used to retrieve the config service format registry
134 // from the supplied Context. 179 // from the supplied Context.
135 func GetFormatterRegistry(c context.Context) *config.FormatterRegistry { 180 func GetFormatterRegistry(c context.Context) *config.FormatterRegistry {
136 return c.Value(&formatRegistryKey).(*config.FormatterRegistry) 181 return c.Value(&formatRegistryKey).(*config.FormatterRegistry)
137 } 182 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698