summaryrefslogtreecommitdiff
path: root/vendor/google.golang.org/grpc/balancer
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/google.golang.org/grpc/balancer')
-rw-r--r--vendor/google.golang.org/grpc/balancer/balancer.go404
-rw-r--r--vendor/google.golang.org/grpc/balancer/base/balancer.go254
-rw-r--r--vendor/google.golang.org/grpc/balancer/base/base.go71
-rw-r--r--vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go74
-rw-r--r--vendor/google.golang.org/grpc/balancer/grpclb/state/state.go51
-rw-r--r--vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go81
6 files changed, 935 insertions, 0 deletions
diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go
new file mode 100644
index 000000000..09d61dd1b
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/balancer.go
@@ -0,0 +1,404 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package balancer defines APIs for load balancing in gRPC.
+// All APIs in this package are experimental.
+package balancer
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "net"
+ "strings"
+
+ "google.golang.org/grpc/channelz"
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/internal"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/resolver"
+ "google.golang.org/grpc/serviceconfig"
+)
+
+var (
+ // m is a map from name to balancer builder.
+ m = make(map[string]Builder)
+)
+
+// Register registers the balancer builder to the balancer map. b.Name
+// (lowercased) will be used as the name registered with this builder. If the
+// Builder implements ConfigParser, ParseConfig will be called when new service
+// configs are received by the resolver, and the result will be provided to the
+// Balancer in UpdateClientConnState.
+//
+// NOTE: this function must only be called during initialization time (i.e. in
+// an init() function), and is not thread-safe. If multiple Balancers are
+// registered with the same name, the one registered last will take effect.
+func Register(b Builder) {
+ m[strings.ToLower(b.Name())] = b
+}
+
+// unregisterForTesting deletes the balancer with the given name from the
+// balancer map.
+//
+// This function is not thread-safe.
+func unregisterForTesting(name string) {
+ delete(m, name)
+}
+
+func init() {
+ internal.BalancerUnregister = unregisterForTesting
+}
+
+// Get returns the resolver builder registered with the given name.
+// Note that the compare is done in a case-insensitive fashion.
+// If no builder is register with the name, nil will be returned.
+func Get(name string) Builder {
+ if b, ok := m[strings.ToLower(name)]; ok {
+ return b
+ }
+ return nil
+}
+
+// A SubConn represents a single connection to a gRPC backend service.
+//
+// Each SubConn contains a list of addresses.
+//
+// All SubConns start in IDLE, and will not try to connect. To trigger the
+// connecting, Balancers must call Connect. If a connection re-enters IDLE,
+// Balancers must call Connect again to trigger a new connection attempt.
+//
+// gRPC will try to connect to the addresses in sequence, and stop trying the
+// remainder once the first connection is successful. If an attempt to connect
+// to all addresses encounters an error, the SubConn will enter
+// TRANSIENT_FAILURE for a backoff period, and then transition to IDLE.
+//
+// Once established, if a connection is lost, the SubConn will transition
+// directly to IDLE.
+//
+// This interface is to be implemented by gRPC. Users should not need their own
+// implementation of this interface. For situations like testing, any
+// implementations should embed this interface. This allows gRPC to add new
+// methods to this interface.
+type SubConn interface {
+ // UpdateAddresses updates the addresses used in this SubConn.
+ // gRPC checks if currently-connected address is still in the new list.
+ // If it's in the list, the connection will be kept.
+ // If it's not in the list, the connection will gracefully closed, and
+ // a new connection will be created.
+ //
+ // This will trigger a state transition for the SubConn.
+ //
+ // Deprecated: This method is now part of the ClientConn interface and will
+ // eventually be removed from here.
+ UpdateAddresses([]resolver.Address)
+ // Connect starts the connecting for this SubConn.
+ Connect()
+ // GetOrBuildProducer returns a reference to the existing Producer for this
+ // ProducerBuilder in this SubConn, or, if one does not currently exist,
+ // creates a new one and returns it. Returns a close function which must
+ // be called when the Producer is no longer needed.
+ GetOrBuildProducer(ProducerBuilder) (p Producer, close func())
+}
+
+// NewSubConnOptions contains options to create new SubConn.
+type NewSubConnOptions struct {
+ // CredsBundle is the credentials bundle that will be used in the created
+ // SubConn. If it's nil, the original creds from grpc DialOptions will be
+ // used.
+ //
+ // Deprecated: Use the Attributes field in resolver.Address to pass
+ // arbitrary data to the credential handshaker.
+ CredsBundle credentials.Bundle
+ // HealthCheckEnabled indicates whether health check service should be
+ // enabled on this SubConn
+ HealthCheckEnabled bool
+}
+
+// State contains the balancer's state relevant to the gRPC ClientConn.
+type State struct {
+ // State contains the connectivity state of the balancer, which is used to
+ // determine the state of the ClientConn.
+ ConnectivityState connectivity.State
+ // Picker is used to choose connections (SubConns) for RPCs.
+ Picker Picker
+}
+
+// ClientConn represents a gRPC ClientConn.
+//
+// This interface is to be implemented by gRPC. Users should not need a
+// brand new implementation of this interface. For the situations like
+// testing, the new implementation should embed this interface. This allows
+// gRPC to add new methods to this interface.
+type ClientConn interface {
+ // NewSubConn is called by balancer to create a new SubConn.
+ // It doesn't block and wait for the connections to be established.
+ // Behaviors of the SubConn can be controlled by options.
+ NewSubConn([]resolver.Address, NewSubConnOptions) (SubConn, error)
+ // RemoveSubConn removes the SubConn from ClientConn.
+ // The SubConn will be shutdown.
+ RemoveSubConn(SubConn)
+ // UpdateAddresses updates the addresses used in the passed in SubConn.
+ // gRPC checks if the currently connected address is still in the new list.
+ // If so, the connection will be kept. Else, the connection will be
+ // gracefully closed, and a new connection will be created.
+ //
+ // This will trigger a state transition for the SubConn.
+ UpdateAddresses(SubConn, []resolver.Address)
+
+ // UpdateState notifies gRPC that the balancer's internal state has
+ // changed.
+ //
+ // gRPC will update the connectivity state of the ClientConn, and will call
+ // Pick on the new Picker to pick new SubConns.
+ UpdateState(State)
+
+ // ResolveNow is called by balancer to notify gRPC to do a name resolving.
+ ResolveNow(resolver.ResolveNowOptions)
+
+ // Target returns the dial target for this ClientConn.
+ //
+ // Deprecated: Use the Target field in the BuildOptions instead.
+ Target() string
+}
+
+// BuildOptions contains additional information for Build.
+type BuildOptions struct {
+ // DialCreds is the transport credentials to use when communicating with a
+ // remote load balancer server. Balancer implementations which do not
+ // communicate with a remote load balancer server can ignore this field.
+ DialCreds credentials.TransportCredentials
+ // CredsBundle is the credentials bundle to use when communicating with a
+ // remote load balancer server. Balancer implementations which do not
+ // communicate with a remote load balancer server can ignore this field.
+ CredsBundle credentials.Bundle
+ // Dialer is the custom dialer to use when communicating with a remote load
+ // balancer server. Balancer implementations which do not communicate with a
+ // remote load balancer server can ignore this field.
+ Dialer func(context.Context, string) (net.Conn, error)
+ // Authority is the server name to use as part of the authentication
+ // handshake when communicating with a remote load balancer server. Balancer
+ // implementations which do not communicate with a remote load balancer
+ // server can ignore this field.
+ Authority string
+ // ChannelzParentID is the parent ClientConn's channelz ID.
+ ChannelzParentID *channelz.Identifier
+ // CustomUserAgent is the custom user agent set on the parent ClientConn.
+ // The balancer should set the same custom user agent if it creates a
+ // ClientConn.
+ CustomUserAgent string
+ // Target contains the parsed address info of the dial target. It is the
+ // same resolver.Target as passed to the resolver. See the documentation for
+ // the resolver.Target type for details about what it contains.
+ Target resolver.Target
+}
+
+// Builder creates a balancer.
+type Builder interface {
+ // Build creates a new balancer with the ClientConn.
+ Build(cc ClientConn, opts BuildOptions) Balancer
+ // Name returns the name of balancers built by this builder.
+ // It will be used to pick balancers (for example in service config).
+ Name() string
+}
+
+// ConfigParser parses load balancer configs.
+type ConfigParser interface {
+ // ParseConfig parses the JSON load balancer config provided into an
+ // internal form or returns an error if the config is invalid. For future
+ // compatibility reasons, unknown fields in the config should be ignored.
+ ParseConfig(LoadBalancingConfigJSON json.RawMessage) (serviceconfig.LoadBalancingConfig, error)
+}
+
+// PickInfo contains additional information for the Pick operation.
+type PickInfo struct {
+ // FullMethodName is the method name that NewClientStream() is called
+ // with. The canonical format is /service/Method.
+ FullMethodName string
+ // Ctx is the RPC's context, and may contain relevant RPC-level information
+ // like the outgoing header metadata.
+ Ctx context.Context
+}
+
+// DoneInfo contains additional information for done.
+type DoneInfo struct {
+ // Err is the rpc error the RPC finished with. It could be nil.
+ Err error
+ // Trailer contains the metadata from the RPC's trailer, if present.
+ Trailer metadata.MD
+ // BytesSent indicates if any bytes have been sent to the server.
+ BytesSent bool
+ // BytesReceived indicates if any byte has been received from the server.
+ BytesReceived bool
+ // ServerLoad is the load received from server. It's usually sent as part of
+ // trailing metadata.
+ //
+ // The only supported type now is *orca_v3.LoadReport.
+ ServerLoad interface{}
+}
+
+var (
+ // ErrNoSubConnAvailable indicates no SubConn is available for pick().
+ // gRPC will block the RPC until a new picker is available via UpdateState().
+ ErrNoSubConnAvailable = errors.New("no SubConn is available")
+ // ErrTransientFailure indicates all SubConns are in TransientFailure.
+ // WaitForReady RPCs will block, non-WaitForReady RPCs will fail.
+ //
+ // Deprecated: return an appropriate error based on the last resolution or
+ // connection attempt instead. The behavior is the same for any non-gRPC
+ // status error.
+ ErrTransientFailure = errors.New("all SubConns are in TransientFailure")
+)
+
+// PickResult contains information related to a connection chosen for an RPC.
+type PickResult struct {
+ // SubConn is the connection to use for this pick, if its state is Ready.
+ // If the state is not Ready, gRPC will block the RPC until a new Picker is
+ // provided by the balancer (using ClientConn.UpdateState). The SubConn
+ // must be one returned by ClientConn.NewSubConn.
+ SubConn SubConn
+
+ // Done is called when the RPC is completed. If the SubConn is not ready,
+ // this will be called with a nil parameter. If the SubConn is not a valid
+ // type, Done may not be called. May be nil if the balancer does not wish
+ // to be notified when the RPC completes.
+ Done func(DoneInfo)
+
+ // Metadata provides a way for LB policies to inject arbitrary per-call
+ // metadata. Any metadata returned here will be merged with existing
+ // metadata added by the client application.
+ //
+ // LB policies with child policies are responsible for propagating metadata
+ // injected by their children to the ClientConn, as part of Pick().
+ Metatada metadata.MD
+}
+
+// TransientFailureError returns e. It exists for backward compatibility and
+// will be deleted soon.
+//
+// Deprecated: no longer necessary, picker errors are treated this way by
+// default.
+func TransientFailureError(e error) error { return e }
+
+// Picker is used by gRPC to pick a SubConn to send an RPC.
+// Balancer is expected to generate a new picker from its snapshot every time its
+// internal state has changed.
+//
+// The pickers used by gRPC can be updated by ClientConn.UpdateState().
+type Picker interface {
+ // Pick returns the connection to use for this RPC and related information.
+ //
+ // Pick should not block. If the balancer needs to do I/O or any blocking
+ // or time-consuming work to service this call, it should return
+ // ErrNoSubConnAvailable, and the Pick call will be repeated by gRPC when
+ // the Picker is updated (using ClientConn.UpdateState).
+ //
+ // If an error is returned:
+ //
+ // - If the error is ErrNoSubConnAvailable, gRPC will block until a new
+ // Picker is provided by the balancer (using ClientConn.UpdateState).
+ //
+ // - If the error is a status error (implemented by the grpc/status
+ // package), gRPC will terminate the RPC with the code and message
+ // provided.
+ //
+ // - For all other errors, wait for ready RPCs will wait, but non-wait for
+ // ready RPCs will be terminated with this error's Error() string and
+ // status code Unavailable.
+ Pick(info PickInfo) (PickResult, error)
+}
+
+// Balancer takes input from gRPC, manages SubConns, and collects and aggregates
+// the connectivity states.
+//
+// It also generates and updates the Picker used by gRPC to pick SubConns for RPCs.
+//
+// UpdateClientConnState, ResolverError, UpdateSubConnState, and Close are
+// guaranteed to be called synchronously from the same goroutine. There's no
+// guarantee on picker.Pick, it may be called anytime.
+type Balancer interface {
+ // UpdateClientConnState is called by gRPC when the state of the ClientConn
+ // changes. If the error returned is ErrBadResolverState, the ClientConn
+ // will begin calling ResolveNow on the active name resolver with
+ // exponential backoff until a subsequent call to UpdateClientConnState
+ // returns a nil error. Any other errors are currently ignored.
+ UpdateClientConnState(ClientConnState) error
+ // ResolverError is called by gRPC when the name resolver reports an error.
+ ResolverError(error)
+ // UpdateSubConnState is called by gRPC when the state of a SubConn
+ // changes.
+ UpdateSubConnState(SubConn, SubConnState)
+ // Close closes the balancer. The balancer is not required to call
+ // ClientConn.RemoveSubConn for its existing SubConns.
+ Close()
+}
+
+// ExitIdler is an optional interface for balancers to implement. If
+// implemented, ExitIdle will be called when ClientConn.Connect is called, if
+// the ClientConn is idle. If unimplemented, ClientConn.Connect will cause
+// all SubConns to connect.
+//
+// Notice: it will be required for all balancers to implement this in a future
+// release.
+type ExitIdler interface {
+ // ExitIdle instructs the LB policy to reconnect to backends / exit the
+ // IDLE state, if appropriate and possible. Note that SubConns that enter
+ // the IDLE state will not reconnect until SubConn.Connect is called.
+ ExitIdle()
+}
+
+// SubConnState describes the state of a SubConn.
+type SubConnState struct {
+ // ConnectivityState is the connectivity state of the SubConn.
+ ConnectivityState connectivity.State
+ // ConnectionError is set if the ConnectivityState is TransientFailure,
+ // describing the reason the SubConn failed. Otherwise, it is nil.
+ ConnectionError error
+}
+
+// ClientConnState describes the state of a ClientConn relevant to the
+// balancer.
+type ClientConnState struct {
+ ResolverState resolver.State
+ // The parsed load balancing configuration returned by the builder's
+ // ParseConfig method, if implemented.
+ BalancerConfig serviceconfig.LoadBalancingConfig
+}
+
+// ErrBadResolverState may be returned by UpdateClientConnState to indicate a
+// problem with the provided name resolver data.
+var ErrBadResolverState = errors.New("bad resolver state")
+
+// A ProducerBuilder is a simple constructor for a Producer. It is used by the
+// SubConn to create producers when needed.
+type ProducerBuilder interface {
+ // Build creates a Producer. The first parameter is always a
+ // grpc.ClientConnInterface (a type to allow creating RPCs/streams on the
+ // associated SubConn), but is declared as interface{} to avoid a
+ // dependency cycle. Should also return a close function that will be
+ // called when all references to the Producer have been given up.
+ Build(grpcClientConnInterface interface{}) (p Producer, close func())
+}
+
+// A Producer is a type shared among potentially many consumers. It is
+// associated with a SubConn, and an implementation will typically contain
+// other methods to provide additional functionality, e.g. configuration or
+// subscription registration.
+type Producer interface {
+}
diff --git a/vendor/google.golang.org/grpc/balancer/base/balancer.go b/vendor/google.golang.org/grpc/balancer/base/balancer.go
new file mode 100644
index 000000000..3929c26d3
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/base/balancer.go
@@ -0,0 +1,254 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package base
+
+import (
+ "errors"
+ "fmt"
+
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/resolver"
+)
+
+var logger = grpclog.Component("balancer")
+
+type baseBuilder struct {
+ name string
+ pickerBuilder PickerBuilder
+ config Config
+}
+
+func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
+ bal := &baseBalancer{
+ cc: cc,
+ pickerBuilder: bb.pickerBuilder,
+
+ subConns: resolver.NewAddressMap(),
+ scStates: make(map[balancer.SubConn]connectivity.State),
+ csEvltr: &balancer.ConnectivityStateEvaluator{},
+ config: bb.config,
+ state: connectivity.Connecting,
+ }
+ // Initialize picker to a picker that always returns
+ // ErrNoSubConnAvailable, because when state of a SubConn changes, we
+ // may call UpdateState with this picker.
+ bal.picker = NewErrPicker(balancer.ErrNoSubConnAvailable)
+ return bal
+}
+
+func (bb *baseBuilder) Name() string {
+ return bb.name
+}
+
+type baseBalancer struct {
+ cc balancer.ClientConn
+ pickerBuilder PickerBuilder
+
+ csEvltr *balancer.ConnectivityStateEvaluator
+ state connectivity.State
+
+ subConns *resolver.AddressMap
+ scStates map[balancer.SubConn]connectivity.State
+ picker balancer.Picker
+ config Config
+
+ resolverErr error // the last error reported by the resolver; cleared on successful resolution
+ connErr error // the last connection error; cleared upon leaving TransientFailure
+}
+
+func (b *baseBalancer) ResolverError(err error) {
+ b.resolverErr = err
+ if b.subConns.Len() == 0 {
+ b.state = connectivity.TransientFailure
+ }
+
+ if b.state != connectivity.TransientFailure {
+ // The picker will not change since the balancer does not currently
+ // report an error.
+ return
+ }
+ b.regeneratePicker()
+ b.cc.UpdateState(balancer.State{
+ ConnectivityState: b.state,
+ Picker: b.picker,
+ })
+}
+
+func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
+ // TODO: handle s.ResolverState.ServiceConfig?
+ if logger.V(2) {
+ logger.Info("base.baseBalancer: got new ClientConn state: ", s)
+ }
+ // Successful resolution; clear resolver error and ensure we return nil.
+ b.resolverErr = nil
+ // addrsSet is the set converted from addrs, it's used for quick lookup of an address.
+ addrsSet := resolver.NewAddressMap()
+ for _, a := range s.ResolverState.Addresses {
+ addrsSet.Set(a, nil)
+ if _, ok := b.subConns.Get(a); !ok {
+ // a is a new address (not existing in b.subConns).
+ sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck})
+ if err != nil {
+ logger.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
+ continue
+ }
+ b.subConns.Set(a, sc)
+ b.scStates[sc] = connectivity.Idle
+ b.csEvltr.RecordTransition(connectivity.Shutdown, connectivity.Idle)
+ sc.Connect()
+ }
+ }
+ for _, a := range b.subConns.Keys() {
+ sci, _ := b.subConns.Get(a)
+ sc := sci.(balancer.SubConn)
+ // a was removed by resolver.
+ if _, ok := addrsSet.Get(a); !ok {
+ b.cc.RemoveSubConn(sc)
+ b.subConns.Delete(a)
+ // Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
+ // The entry will be deleted in UpdateSubConnState.
+ }
+ }
+ // If resolver state contains no addresses, return an error so ClientConn
+ // will trigger re-resolve. Also records this as an resolver error, so when
+ // the overall state turns transient failure, the error message will have
+ // the zero address information.
+ if len(s.ResolverState.Addresses) == 0 {
+ b.ResolverError(errors.New("produced zero addresses"))
+ return balancer.ErrBadResolverState
+ }
+
+ b.regeneratePicker()
+ b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker})
+ return nil
+}
+
+// mergeErrors builds an error from the last connection error and the last
+// resolver error. Must only be called if b.state is TransientFailure.
+func (b *baseBalancer) mergeErrors() error {
+ // connErr must always be non-nil unless there are no SubConns, in which
+ // case resolverErr must be non-nil.
+ if b.connErr == nil {
+ return fmt.Errorf("last resolver error: %v", b.resolverErr)
+ }
+ if b.resolverErr == nil {
+ return fmt.Errorf("last connection error: %v", b.connErr)
+ }
+ return fmt.Errorf("last connection error: %v; last resolver error: %v", b.connErr, b.resolverErr)
+}
+
+// regeneratePicker takes a snapshot of the balancer, and generates a picker
+// from it. The picker is
+// - errPicker if the balancer is in TransientFailure,
+// - built by the pickerBuilder with all READY SubConns otherwise.
+func (b *baseBalancer) regeneratePicker() {
+ if b.state == connectivity.TransientFailure {
+ b.picker = NewErrPicker(b.mergeErrors())
+ return
+ }
+ readySCs := make(map[balancer.SubConn]SubConnInfo)
+
+ // Filter out all ready SCs from full subConn map.
+ for _, addr := range b.subConns.Keys() {
+ sci, _ := b.subConns.Get(addr)
+ sc := sci.(balancer.SubConn)
+ if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
+ readySCs[sc] = SubConnInfo{Address: addr}
+ }
+ }
+ b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs})
+}
+
+func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
+ s := state.ConnectivityState
+ if logger.V(2) {
+ logger.Infof("base.baseBalancer: handle SubConn state change: %p, %v", sc, s)
+ }
+ oldS, ok := b.scStates[sc]
+ if !ok {
+ if logger.V(2) {
+ logger.Infof("base.baseBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
+ }
+ return
+ }
+ if oldS == connectivity.TransientFailure &&
+ (s == connectivity.Connecting || s == connectivity.Idle) {
+ // Once a subconn enters TRANSIENT_FAILURE, ignore subsequent IDLE or
+ // CONNECTING transitions to prevent the aggregated state from being
+ // always CONNECTING when many backends exist but are all down.
+ if s == connectivity.Idle {
+ sc.Connect()
+ }
+ return
+ }
+ b.scStates[sc] = s
+ switch s {
+ case connectivity.Idle:
+ sc.Connect()
+ case connectivity.Shutdown:
+ // When an address was removed by resolver, b called RemoveSubConn but
+ // kept the sc's state in scStates. Remove state for this sc here.
+ delete(b.scStates, sc)
+ case connectivity.TransientFailure:
+ // Save error to be reported via picker.
+ b.connErr = state.ConnectionError
+ }
+
+ b.state = b.csEvltr.RecordTransition(oldS, s)
+
+ // Regenerate picker when one of the following happens:
+ // - this sc entered or left ready
+ // - the aggregated state of balancer is TransientFailure
+ // (may need to update error message)
+ if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||
+ b.state == connectivity.TransientFailure {
+ b.regeneratePicker()
+ }
+ b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker})
+}
+
+// Close is a nop because base balancer doesn't have internal state to clean up,
+// and it doesn't need to call RemoveSubConn for the SubConns.
+func (b *baseBalancer) Close() {
+}
+
+// ExitIdle is a nop because the base balancer attempts to stay connected to
+// all SubConns at all times.
+func (b *baseBalancer) ExitIdle() {
+}
+
+// NewErrPicker returns a Picker that always returns err on Pick().
+func NewErrPicker(err error) balancer.Picker {
+ return &errPicker{err: err}
+}
+
+// NewErrPickerV2 is temporarily defined for backward compatibility reasons.
+//
+// Deprecated: use NewErrPicker instead.
+var NewErrPickerV2 = NewErrPicker
+
+type errPicker struct {
+ err error // Pick() always returns this err.
+}
+
+func (p *errPicker) Pick(info balancer.PickInfo) (balancer.PickResult, error) {
+ return balancer.PickResult{}, p.err
+}
diff --git a/vendor/google.golang.org/grpc/balancer/base/base.go b/vendor/google.golang.org/grpc/balancer/base/base.go
new file mode 100644
index 000000000..e31d76e33
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/base/base.go
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package base defines a balancer base that can be used to build balancers with
+// different picking algorithms.
+//
+// The base balancer creates a new SubConn for each resolved address. The
+// provided picker will only be notified about READY SubConns.
+//
+// This package is the base of round_robin balancer, its purpose is to be used
+// to build round_robin like balancers with complex picking algorithms.
+// Balancers with more complicated logic should try to implement a balancer
+// builder from scratch.
+//
+// All APIs in this package are experimental.
+package base
+
+import (
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/resolver"
+)
+
+// PickerBuilder creates balancer.Picker.
+type PickerBuilder interface {
+ // Build returns a picker that will be used by gRPC to pick a SubConn.
+ Build(info PickerBuildInfo) balancer.Picker
+}
+
+// PickerBuildInfo contains information needed by the picker builder to
+// construct a picker.
+type PickerBuildInfo struct {
+ // ReadySCs is a map from all ready SubConns to the Addresses used to
+ // create them.
+ ReadySCs map[balancer.SubConn]SubConnInfo
+}
+
+// SubConnInfo contains information about a SubConn created by the base
+// balancer.
+type SubConnInfo struct {
+ Address resolver.Address // the address used to create this SubConn
+}
+
+// Config contains the config info about the base balancer builder.
+type Config struct {
+ // HealthCheck indicates whether health checking should be enabled for this specific balancer.
+ HealthCheck bool
+}
+
+// NewBalancerBuilder returns a base balancer builder configured by the provided config.
+func NewBalancerBuilder(name string, pb PickerBuilder, config Config) balancer.Builder {
+ return &baseBuilder{
+ name: name,
+ pickerBuilder: pb,
+ config: config,
+ }
+}
diff --git a/vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go b/vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go
new file mode 100644
index 000000000..c33413581
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright 2022 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package balancer
+
+import "google.golang.org/grpc/connectivity"
+
+// ConnectivityStateEvaluator takes the connectivity states of multiple SubConns
+// and returns one aggregated connectivity state.
+//
+// It's not thread safe.
+type ConnectivityStateEvaluator struct {
+ numReady uint64 // Number of addrConns in ready state.
+ numConnecting uint64 // Number of addrConns in connecting state.
+ numTransientFailure uint64 // Number of addrConns in transient failure state.
+ numIdle uint64 // Number of addrConns in idle state.
+}
+
+// RecordTransition records state change happening in subConn and based on that
+// it evaluates what aggregated state should be.
+//
+// - If at least one SubConn in Ready, the aggregated state is Ready;
+// - Else if at least one SubConn in Connecting, the aggregated state is Connecting;
+// - Else if at least one SubConn is Idle, the aggregated state is Idle;
+// - Else if at least one SubConn is TransientFailure (or there are no SubConns), the aggregated state is Transient Failure.
+//
+// Shutdown is not considered.
+func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State {
+ // Update counters.
+ for idx, state := range []connectivity.State{oldState, newState} {
+ updateVal := 2*uint64(idx) - 1 // -1 for oldState and +1 for new.
+ switch state {
+ case connectivity.Ready:
+ cse.numReady += updateVal
+ case connectivity.Connecting:
+ cse.numConnecting += updateVal
+ case connectivity.TransientFailure:
+ cse.numTransientFailure += updateVal
+ case connectivity.Idle:
+ cse.numIdle += updateVal
+ }
+ }
+ return cse.CurrentState()
+}
+
+// CurrentState returns the current aggregate conn state by evaluating the counters
+func (cse *ConnectivityStateEvaluator) CurrentState() connectivity.State {
+ // Evaluate.
+ if cse.numReady > 0 {
+ return connectivity.Ready
+ }
+ if cse.numConnecting > 0 {
+ return connectivity.Connecting
+ }
+ if cse.numIdle > 0 {
+ return connectivity.Idle
+ }
+ return connectivity.TransientFailure
+}
diff --git a/vendor/google.golang.org/grpc/balancer/grpclb/state/state.go b/vendor/google.golang.org/grpc/balancer/grpclb/state/state.go
new file mode 100644
index 000000000..4ecfa1c21
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/grpclb/state/state.go
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright 2020 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package state declares grpclb types to be set by resolvers wishing to pass
+// information to grpclb via resolver.State Attributes.
+package state
+
+import (
+ "google.golang.org/grpc/resolver"
+)
+
+// keyType is the key to use for storing State in Attributes.
+type keyType string
+
+const key = keyType("grpc.grpclb.state")
+
+// State contains gRPCLB-relevant data passed from the name resolver.
+type State struct {
+ // BalancerAddresses contains the remote load balancer address(es). If
+ // set, overrides any resolver-provided addresses with Type of GRPCLB.
+ BalancerAddresses []resolver.Address
+}
+
+// Set returns a copy of the provided state with attributes containing s. s's
+// data should not be mutated after calling Set.
+func Set(state resolver.State, s *State) resolver.State {
+ state.Attributes = state.Attributes.WithValue(key, s)
+ return state
+}
+
+// Get returns the grpclb State in the resolver.State, or nil if not present.
+// The returned data should not be mutated.
+func Get(state resolver.State) *State {
+ s, _ := state.Attributes.Value(key).(*State)
+ return s
+}
diff --git a/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
new file mode 100644
index 000000000..f7031ad22
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
@@ -0,0 +1,81 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package roundrobin defines a roundrobin balancer. Roundrobin balancer is
+// installed as one of the default balancers in gRPC, users don't need to
+// explicitly install this balancer.
+package roundrobin
+
+import (
+ "sync/atomic"
+
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/balancer/base"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/internal/grpcrand"
+)
+
+// Name is the name of round_robin balancer.
+const Name = "round_robin"
+
+var logger = grpclog.Component("roundrobin")
+
+// newBuilder creates a new roundrobin balancer builder.
+func newBuilder() balancer.Builder {
+ return base.NewBalancerBuilder(Name, &rrPickerBuilder{}, base.Config{HealthCheck: true})
+}
+
+func init() {
+ balancer.Register(newBuilder())
+}
+
+type rrPickerBuilder struct{}
+
+func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker {
+ logger.Infof("roundrobinPicker: Build called with info: %v", info)
+ if len(info.ReadySCs) == 0 {
+ return base.NewErrPicker(balancer.ErrNoSubConnAvailable)
+ }
+ scs := make([]balancer.SubConn, 0, len(info.ReadySCs))
+ for sc := range info.ReadySCs {
+ scs = append(scs, sc)
+ }
+ return &rrPicker{
+ subConns: scs,
+ // Start at a random index, as the same RR balancer rebuilds a new
+ // picker when SubConn states change, and we don't want to apply excess
+ // load to the first server in the list.
+ next: uint32(grpcrand.Intn(len(scs))),
+ }
+}
+
+type rrPicker struct {
+ // subConns is the snapshot of the roundrobin balancer when this picker was
+ // created. The slice is immutable. Each Get() will do a round robin
+ // selection from it and return the selected SubConn.
+ subConns []balancer.SubConn
+ next uint32
+}
+
+func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
+ subConnsLen := uint32(len(p.subConns))
+ nextIndex := atomic.AddUint32(&p.next, 1)
+
+ sc := p.subConns[nextIndex%subConnsLen]
+ return balancer.PickResult{SubConn: sc}, nil
+}