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

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

Issue 2576923003: Implement config service cache on top of datastore (Closed)
Patch Set: Relocated, fix, split integration test, rebase. 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
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/luci_config/appengine/backend/datastore"
15 "github.com/luci/luci-go/luci_config/appengine/backend/memcache" 16 "github.com/luci/luci-go/luci_config/appengine/backend/memcache"
16 gaeformat "github.com/luci/luci-go/luci_config/appengine/format" 17 gaeformat "github.com/luci/luci-go/luci_config/appengine/format"
17 "github.com/luci/luci-go/luci_config/server/cfgclient/backend" 18 "github.com/luci/luci-go/luci_config/server/cfgclient/backend"
18 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/caching" 19 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/caching"
19 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/client" 20 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/client"
20 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/erroring" 21 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/erroring"
21 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/format" 22 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/format"
22 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/testconfig " 23 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/testconfig "
24 "github.com/luci/luci-go/server/router"
23 25
24 "github.com/luci/gae/service/info" 26 "github.com/luci/gae/service/info"
25 27
26 "golang.org/x/net/context" 28 "golang.org/x/net/context"
27 ) 29 )
28 30
29 // ErrNotConfigured is returned by cfgclient methods if the config service URL 31 // ErrNotConfigured is returned by cfgclient methods if the config service URL
30 // is not set. Usually happens for new apps. 32 // is not set. Usually happens for new apps.
31 var ErrNotConfigured = errors.New("config service URL is not set in settings") 33 var ErrNotConfigured = errors.New("config service URL is not set in settings")
32 34
33 // devCfgDir is a name of the directory with config files when running in 35 // devCfgDir is a name of the directory with config files when running in
34 // local dev appserver model. See New for details. 36 // local dev appserver model. See New for details.
35 const devCfgDir = "devcfg" 37 const devCfgDir = "devcfg"
36 38
39 // InstallCacheCronHandler installs the configuration service datastore caching
40 // cron handler. This must be installed, and an associated cron must be set up,
41 // if datastore caching is enabled.
42 //
43 // The cron should be configured to hit the handler at:
44 // /admin/config/cache/manager
45 func InstallCacheCronHandler(r *router.Router, base router.MiddlewareChain) {
46 installCacheCronHandlerImpl(r, base, nil)
47 }
48
49 // Install our cache cron handler into the supplied Router.
50 //
51 // bf is a generator function used to get the primary (service) Backend to build
52 // on top of. If nil, the "production" (one used by Use) Backend will be used.
53 func installCacheCronHandlerImpl(r *router.Router, base router.MiddlewareChain, be backend.B) {
54 base = base.Extend(func(c *router.Context, next router.Handler) {
55 // Install our Backend into our Context.
56 c.Context = installConfigBackend(c.Context, mustFetchCachedSetti ngs(c.Context), be, true)
57 next(c)
58 })
59
60 datastore.Cache.InstallCronRoute("/admin/config/cache/manager", r, base)
61 }
62
37 // Use installs the default luci-config client. 63 // Use installs the default luci-config client.
38 // 64 //
39 // The client is configured to use luci-config URL specified in the settings, 65 // The client is configured to use luci-config URL specified in the settings,
40 // using GAE app service account for authentication. 66 // using GAE app service account for authentication.
41 // 67 //
42 // If running in prod, and the settings don't specify luci-config URL, produces 68 // If running in prod, and the settings don't specify luci-config URL, produces
43 // an implementation of backend.B that returns ErrNotConfigured from all 69 // an implementation of backend.B that returns ErrNotConfigured from all
44 // methods. 70 // methods.
45 // 71 //
46 // If running on devserver, and the settings don't specify luci-config URL, 72 // If running on devserver, and the settings don't specify luci-config URL,
47 // returns a filesystem-based implementation that reads configs from a directory 73 // returns a filesystem-based implementation that reads configs from a directory
48 // (or a symlink) named 'devcfg' located in the GAE module directory (where 74 // (or a symlink) named 'devcfg' located in the GAE module directory (where
49 // app.yaml is) or its immediate parent directory. 75 // app.yaml is) or its immediate parent directory.
50 // 76 //
51 // If such directory can not be located, produces an implementation of 77 // If such directory can not be located, produces an implementation of
52 // cfgclient that returns errors from all methods. 78 // cfgclient that returns errors from all methods.
53 // 79 //
54 // Panics if it can't load the settings (should not happen since they are in 80 // Panics if it can't load the settings (should not happen since they are in
55 // the local memory cache usually). 81 // the local memory cache usually).
56 func Use(c context.Context) context.Context { return useImpl(c, nil) } 82 func Use(c context.Context) context.Context { return useImpl(c, nil) }
57 83
58 func useImpl(c context.Context, be backend.B) context.Context { 84 func useImpl(c context.Context, be backend.B) context.Context {
59 » return installConfigBackend(c, mustFetchCachedSettings(c), be) 85 » return installConfigBackend(c, mustFetchCachedSettings(c), be, false)
60 } 86 }
61 87
62 func installConfigBackend(c context.Context, s *Settings, be backend.B) context. Context { 88 func installConfigBackend(c context.Context, s *Settings, be backend.B, dsCron b ool) context.Context {
63 if be == nil { 89 if be == nil {
64 // Non-testing, build a Backend. 90 // Non-testing, build a Backend.
65 be = getPrimaryBackend(c, s) 91 be = getPrimaryBackend(c, s)
66 } 92 }
67 93
68 // Install a FormatRegistry. Register common config service protobufs wi th it. 94 // Install a FormatRegistry. Register common config service protobufs wi th it.
69 c = gaeformat.WithRegistry(c, gaeformat.Default()) 95 c = gaeformat.WithRegistry(c, gaeformat.Default())
70 96
71 be = &format.Backend{ 97 be = &format.Backend{
72 B: be, 98 B: be,
73 GetRegistry: gaeformat.GetRegistry, 99 GetRegistry: gaeformat.GetRegistry,
74 } 100 }
75 101
76 // Apply caching configuration. 102 // Apply caching configuration.
77 exp := time.Duration(s.CacheExpirationSec) * time.Second 103 exp := time.Duration(s.CacheExpirationSec) * time.Second
78 if exp > 0 { 104 if exp > 0 {
79 // Add a ProcCache, backed by memcache. 105 // Add a ProcCache, backed by memcache.
80 be = memcache.Backend(be, exp) 106 be = memcache.Backend(be, exp)
81 be = caching.ProcCache(be, exp) 107 be = caching.ProcCache(be, exp)
108
109 // If our datastore cache is enabled, install a handler for refr esh. This
110 // will be loaded by dsCache's "HandlerFunc".
111 if s.DatastoreCacheMode != dsCacheDisabled {
112 dsc := datastore.Config{
113 RefreshInterval: exp,
114 FailOpen: s.DatastoreCacheMode == dsCache Enabled,
115 }
116
117 if !dsCron {
118 // For non-cron, install the datastore cache Bac kend.
119 be = dsc.Backend(be)
120 } else {
121 // For cron, do not install the datastore cache Backend. Instead,
122 // install a lasting Handler into the Context to be used for cache
123 // resolution. This is necessary since resolutio n calls will not be
124 // the result of an actual resolution command (e .g., cache.Get).
125 c = dsc.WithHandler(c, datastore.CronLoader(be), datastore.RPCDeadline)
126 }
127 }
82 } 128 }
83 129
84 c = backend.WithBackend(c, be) 130 c = backend.WithBackend(c, be)
85 return c 131 return c
86 } 132 }
87 133
88 func getPrimaryBackend(c context.Context, settings *Settings) backend.B { 134 func getPrimaryBackend(c context.Context, settings *Settings) backend.B {
89 // Identify our config service backend (in testing, it will be supplied) . 135 // Identify our config service backend (in testing, it will be supplied) .
90 if settings.ConfigServiceURL == "" { 136 if settings.ConfigServiceURL == "" {
91 if info.IsDevAppServer(c) { 137 if info.IsDevAppServer(c) {
(...skipping 21 matching lines...) Expand all
113 if err != nil { 159 if err != nil {
114 return erroring.New(err) 160 return erroring.New(err)
115 } 161 }
116 return &client.Backend{&testconfig.Provider{ 162 return &client.Backend{&testconfig.Provider{
117 Base: fs, 163 Base: fs,
118 }} 164 }}
119 } 165 }
120 } 166 }
121 return erroring.New(fmt.Errorf("luci-config: could not find local config s in any of %s", candidates)) 167 return erroring.New(fmt.Errorf("luci-config: could not find local config s in any of %s", candidates))
122 } 168 }
OLDNEW
« no previous file with comments | « luci_config/appengine/backend/datastore/ds_test.go ('k') | luci_config/appengine/gaeconfig/default_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698