go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/module/deps.go (about) 1 // Copyright 2020 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 module 16 17 import ( 18 "fmt" 19 20 "go.chromium.org/luci/common/data/stringset" 21 ) 22 23 var registered stringset.Set 24 25 // Name is a name of a registered module. 26 // 27 // Usually it is a full name of the go package that implements the module, but 28 // it can be arbitrary as long as it is unique within a server. Attempting to 29 // register two identical names results in a panic during the server startup. 30 // 31 // Names are usually registered during init-time via RegisterName and stored as 32 // global variables, so they can be referred to in Dependencies() implementation 33 // of other modules. 34 type Name struct { 35 name string 36 } 37 38 // String returns the name string. 39 func (n Name) String() string { return n.name } 40 41 // Valid is true if this name is not empty. 42 func (n Name) Valid() bool { return n.name != "" } 43 44 // RegisterName registers a module name and returns it. 45 // 46 // It's the only way to construct new Name instances. Panics if such name was 47 // already registered. 48 func RegisterName(name string) Name { 49 if registered.Has(name) { 50 panic(fmt.Sprintf("module name %q has already been registered", name)) 51 } 52 if registered == nil { 53 registered = stringset.New(1) 54 } 55 registered.Add(name) 56 return Name{name} 57 } 58 59 // Dependency represents a dependency on a module. 60 // 61 // It can be either required or optional. If a module A declares a require 62 // dependency on another module B, then A cannot function without B at all. Also 63 // B will be initialized before A. 64 // 65 // If the dependency on B is optional, A will start even if B is not present. 66 // But if B is present, it will be initialized before A. 67 // 68 // Dependency cycles result in an undefined order of initialization. 69 type Dependency struct { 70 name Name 71 required bool 72 } 73 74 // RequiredDependency declares a required dependency. 75 func RequiredDependency(dep Name) Dependency { 76 return Dependency{name: dep, required: true} 77 } 78 79 // OptionalDependency declares an optional dependency. 80 func OptionalDependency(dep Name) Dependency { 81 return Dependency{name: dep, required: false} 82 } 83 84 // Dependency is the name of a module to depend on. 85 func (d Dependency) Dependency() Name { return d.name } 86 87 // Required is true if this is a required dependency. 88 func (d Dependency) Required() bool { return d.required }