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 }