go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/resultdb/internal/config/config.go (about) 1 // Copyright 2024 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package config 16 17 import ( 18 "context" 19 20 "google.golang.org/protobuf/proto" 21 22 "go.chromium.org/luci/common/errors" 23 "go.chromium.org/luci/common/logging" 24 "go.chromium.org/luci/config" 25 "go.chromium.org/luci/config/server/cfgcache" 26 "go.chromium.org/luci/config/validation" 27 "go.chromium.org/luci/gae/service/datastore" 28 29 configpb "go.chromium.org/luci/resultdb/proto/config" 30 ) 31 32 const serviceConfigFilename = "config.cfg" 33 34 // Cached service-level config 35 var cachedServiceCfg = cfgcache.Register(&cfgcache.Entry{ 36 Path: serviceConfigFilename, 37 Type: (*configpb.Config)(nil), 38 Validator: func(ctx *validation.Context, msg proto.Message) error { 39 validateServiceConfig(ctx, msg.(*configpb.Config)) 40 return nil 41 }, 42 }) 43 44 // UpdateConfig is called from a cron periodically; it fetches the latest 45 // service-wide config and project config from the LUCI Config service 46 // and caches them into the datastore 47 func UpdateConfig(ctx context.Context) error { 48 var errs []error 49 err := UpdateProjects(ctx) 50 if err != nil { 51 errs = append(errs, errors.Annotate(err, "update project configs").Err()) 52 } 53 err = UpdateServiceConfig(ctx) 54 if err != nil { 55 errs = append(errs, errors.Annotate(err, "update service configs").Err()) 56 } 57 if len(errs) > 0 { 58 return errors.NewMultiError(errs...) 59 } 60 return nil 61 62 } 63 64 // UpdateServiceConfig fetches the latest service config and caches it in datastore. 65 func UpdateServiceConfig(ctx context.Context) error { 66 _, err := cachedServiceCfg.Update(ctx, nil) 67 return err 68 } 69 70 // GetServiceConfig returns the cached service-level config 71 func GetServiceConfig(ctx context.Context) (*configpb.Config, error) { 72 cfg, err := cachedServiceCfg.Get(ctx, nil) 73 if err != nil { 74 err = errors.Annotate(err, "failed to get cached config").Err() 75 logging.Errorf(ctx, "%s", err.Error()) 76 return nil, err 77 } 78 79 return cfg.(*configpb.Config), nil 80 } 81 82 // SetServiceConfig installs the service into the context ctx. 83 // This is only used for the purpose of testing. 84 func SetServiceConfig(ctx context.Context, cfg *configpb.Config) error { 85 testable := datastore.GetTestable(ctx) 86 if testable == nil { 87 return errors.New("SetServiceConfig should only be used with testable datastore implementations") 88 } 89 err := cachedServiceCfg.Set(ctx, cfg, &config.Meta{}) 90 if err != nil { 91 return err 92 } 93 testable.CatchupIndexes() 94 return nil 95 }