go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/logdog/server/service/main.go (about) 1 // Copyright 2021 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 service 16 17 import ( 18 "context" 19 "flag" 20 21 "go.chromium.org/luci/server" 22 "go.chromium.org/luci/server/gaeemulation" 23 "go.chromium.org/luci/server/module" 24 25 logdog "go.chromium.org/luci/logdog/api/endpoints/coordinator/services/v1" 26 "go.chromium.org/luci/logdog/common/storage" 27 "go.chromium.org/luci/logdog/common/storage/bigtable" 28 "go.chromium.org/luci/logdog/server/config" 29 ) 30 31 // Implementations contains some preconfigured Logdog subsystem clients. 32 type Implementations struct { 33 Storage storage.Storage // the intermediate storage 34 Coordinator logdog.ServicesClient // the bundling coordinator client 35 } 36 37 // MainCfg are global configuration options for `Main`. 38 // 39 // The settings here are tied to the code-to-be-executed, rather than the 40 // the execution environment for the code. 41 type MainCfg struct { 42 // The AppProfile for the global BigTable client for this service. 43 // 44 // If empty, the default application profile will be used. 45 BigTableAppProfile string 46 } 47 48 // Main initializes and runs a logdog microservice process. 49 func Main(cfg MainCfg, init func(srv *server.Server, impl *Implementations) error) { 50 modules := []module.Module{ 51 gaeemulation.NewModuleFromFlags(), // for fetching LUCI project configs 52 } 53 54 coordFlags := coordinatorFlags{} 55 coordFlags.register(flag.CommandLine) 56 57 storageFlags := bigtable.Flags{ 58 AppProfile: cfg.BigTableAppProfile, 59 } 60 storageFlags.Register(flag.CommandLine) 61 62 server.Main(nil, modules, func(srv *server.Server) error { 63 if err := coordFlags.validate(); err != nil { 64 return err 65 } 66 if err := storageFlags.Validate(); err != nil { 67 return err 68 } 69 70 // Add an in-memory config caching to avoid hitting datastore all the time. 71 srv.Context = config.WithStore(srv.Context, &config.Store{}) 72 73 // Initialize our Storage. 74 st, err := bigtable.StorageFromFlags(srv.Context, &storageFlags) 75 if err != nil { 76 return err 77 } 78 srv.RegisterCleanup(func(context.Context) { st.Close() }) 79 80 // Initialize a Coordinator client that bundles requests together. 81 coordClient, err := coordinator(srv.Context, &coordFlags) 82 if err != nil { 83 return err 84 } 85 srv.RegisterCleanup(func(context.Context) { coordClient.Flush() }) 86 87 // Let the particular microservice initialize itself. 88 return init(srv, &Implementations{ 89 Storage: st, 90 Coordinator: coordClient, 91 }) 92 }) 93 }