go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/config/appengine/gaeconfig/lazy.go (about) 1 // Copyright 2023 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 gaeconfig 16 17 import ( 18 "context" 19 "sync" 20 21 "go.chromium.org/luci/config" 22 ) 23 24 // lazyConfigClient is a lazily-constructed configClient that implements 25 // config.Interface. The client will be initialized by the provided 26 // clientFactory function. 27 type lazyConfigClient struct { 28 clientFactory func(ctx context.Context) config.Interface 29 30 inner config.Interface 31 innerOnce sync.Once 32 } 33 34 var _ config.Interface = (*lazyConfigClient)(nil) 35 36 func newLazyConfigClient(factory func(ctx context.Context) config.Interface) *lazyConfigClient { 37 return &lazyConfigClient{ 38 clientFactory: factory, 39 } 40 } 41 42 func (client *lazyConfigClient) lazyInit(ctx context.Context) { 43 client.innerOnce.Do(func() { 44 client.inner = client.clientFactory(ctx) 45 }) 46 } 47 48 // GetConfig implements config.Interface. 49 func (client *lazyConfigClient) GetConfig(ctx context.Context, configSet config.Set, path string, metaOnly bool) (*config.Config, error) { 50 client.lazyInit(ctx) 51 return client.inner.GetConfig(ctx, configSet, path, metaOnly) 52 } 53 54 // GetConfigs implements config.Interface. 55 func (client *lazyConfigClient) GetConfigs(ctx context.Context, configSet config.Set, filter func(path string) bool, metaOnly bool) (map[string]config.Config, error) { 56 client.lazyInit(ctx) 57 return client.inner.GetConfigs(ctx, configSet, filter, metaOnly) 58 } 59 60 // GetProjectConfigs implements config.Interface. 61 func (client *lazyConfigClient) GetProjectConfigs(ctx context.Context, path string, metaOnly bool) ([]config.Config, error) { 62 client.lazyInit(ctx) 63 return client.inner.GetProjectConfigs(ctx, path, metaOnly) 64 } 65 66 // GetProjects implements config.Interface. 67 func (client *lazyConfigClient) GetProjects(ctx context.Context) ([]config.Project, error) { 68 client.lazyInit(ctx) 69 return client.inner.GetProjects(ctx) 70 } 71 72 // ListFiles implements config.Interface. 73 func (client *lazyConfigClient) ListFiles(ctx context.Context, configSet config.Set) ([]string, error) { 74 client.lazyInit(ctx) 75 return client.inner.ListFiles(ctx, configSet) 76 } 77 78 // Close implements config.Interface. 79 func (client *lazyConfigClient) Close() error { 80 // This is potentially racy if client is initialized and closed at the same 81 // time. But in this case, Close is never called so it's not a big deal. 82 if client.inner != nil { 83 return client.inner.Close() 84 } 85 return nil 86 }