go.uber.org/yarpc@v1.72.1/yarpcconfig/kit.go (about)

     1  // Copyright (c) 2022 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package yarpcconfig
    22  
    23  import (
    24  	"errors"
    25  	"fmt"
    26  	"reflect"
    27  	"sort"
    28  	"strings"
    29  
    30  	"go.uber.org/yarpc/api/transport"
    31  	"go.uber.org/yarpc/internal/interpolate"
    32  )
    33  
    34  // Kit is an opaque object that carries context for the Configurator. Build
    35  // functions that receive this object MUST NOT modify it.
    36  type Kit struct {
    37  	c *Configurator
    38  
    39  	name string
    40  
    41  	// outboundName is the name of the outbound. It is set in the Kit used for
    42  	// building outbound.
    43  	outboundName string
    44  
    45  	// Used to resolve interpolated variables.
    46  	resolver interpolate.VariableResolver
    47  
    48  	// TransportSpec currently being used. This may or may not be set.
    49  	transportSpec *compiledTransportSpec
    50  }
    51  
    52  // Returns a shallow copy of this Kit with spec set to the given value.
    53  func (k *Kit) withTransportSpec(spec *compiledTransportSpec) *Kit {
    54  	newK := *k
    55  	newK.transportSpec = spec
    56  	return &newK
    57  }
    58  
    59  // Returns a shallow copy of this Kit with outbound name set to given value.
    60  func (k *Kit) withOutboundName(name string) *Kit {
    61  	newK := *k
    62  	newK.outboundName = name
    63  	return &newK
    64  }
    65  
    66  // ServiceName returns the name of the service for which components are being
    67  // built.
    68  func (k *Kit) ServiceName() string { return k.name }
    69  
    70  // OutboundServiceName returns the name of the service for which outbound is
    71  // being built.
    72  func (k *Kit) OutboundServiceName() string { return k.outboundName }
    73  
    74  var _typeOfKit = reflect.TypeOf((*Kit)(nil))
    75  
    76  func (k *Kit) maybePeerChooserSpec(name string) *compiledPeerChooserSpec {
    77  	return k.c.knownPeerChoosers[name]
    78  }
    79  
    80  func (k *Kit) peerListSpec(name string) (*compiledPeerListSpec, error) {
    81  	if spec := k.c.knownPeerLists[name]; spec != nil {
    82  		return spec, nil
    83  	}
    84  
    85  	msg := fmt.Sprintf("no recognized peer list or chooser %q", name)
    86  	if available := k.peerChooserAndListSpecNames(); len(available) > 0 {
    87  		msg = fmt.Sprintf("%s; need one of %s", msg, strings.Join(available, ", "))
    88  	}
    89  
    90  	return nil, errors.New(msg)
    91  }
    92  
    93  func (k *Kit) peerChooserPreset(name string) (*compiledPeerChooserPreset, error) {
    94  	if k.transportSpec == nil {
    95  		// Currently, transportspec is set only if we're inside build*Outbound.
    96  		return nil, errors.New(
    97  			"invalid Kit: make sure you passed in the same Kit your Build function received")
    98  	}
    99  
   100  	if spec := k.transportSpec.PeerChooserPresets[name]; spec != nil {
   101  		return spec, nil
   102  	}
   103  
   104  	available := make([]string, 0, len(k.transportSpec.PeerChooserPresets))
   105  	for name := range k.transportSpec.PeerChooserPresets {
   106  		available = append(available, name)
   107  	}
   108  
   109  	msg := fmt.Sprintf("no recognized peer chooser preset %q", name)
   110  	if len(available) > 0 {
   111  		msg = fmt.Sprintf("%s; need one of %s", msg, strings.Join(available, ", "))
   112  	}
   113  
   114  	return nil, errors.New(msg)
   115  }
   116  
   117  func (k *Kit) peerChooserAndListSpecNames() (names []string) {
   118  	for name := range k.c.knownPeerLists {
   119  		names = append(names, name)
   120  	}
   121  	for name := range k.c.knownPeerChoosers {
   122  		names = append(names, name)
   123  	}
   124  	sort.Strings(names)
   125  	return
   126  }
   127  
   128  func (k *Kit) peerListUpdaterSpec(name string) *compiledPeerListUpdaterSpec {
   129  	return k.c.knownPeerListUpdaters[name]
   130  }
   131  
   132  func (k *Kit) peerListUpdaterSpecNames() (names []string) {
   133  	for name := range k.c.knownPeerListUpdaters {
   134  		names = append(names, name)
   135  	}
   136  	sort.Strings(names)
   137  	return
   138  }
   139  
   140  // Compressor returns the known compressor for the given name or nil if the
   141  // named compressor is not known.
   142  func (k *Kit) Compressor(name string) transport.Compressor {
   143  	return k.c.knownCompressors[name]
   144  }