dubbo.apache.org/dubbo-go/v3@v3.1.1/xds/utils/resolver/config_selector.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  /*
    19   *
    20   * Copyright 2021 gRPC authors.
    21   *
    22   */
    23  
    24  // Package resolver provides internal resolver-related functionality.
    25  package resolver
    26  
    27  import (
    28  	"context"
    29  	"sync"
    30  )
    31  
    32  import (
    33  	"google.golang.org/grpc/metadata"
    34  
    35  	"google.golang.org/grpc/resolver"
    36  )
    37  
    38  import (
    39  	"dubbo.apache.org/dubbo-go/v3/xds/utils/serviceconfig"
    40  )
    41  
    42  // ConfigSelector controls what configuration to use for every RPC.
    43  type ConfigSelector interface {
    44  	// Selects the configuration for the RPC, or terminates it using the error.
    45  	// This error will be converted by the gRPC library to a status error with
    46  	// code UNKNOWN if it is not returned as a status error.
    47  	SelectConfig(RPCInfo) (*RPCConfig, error)
    48  }
    49  
    50  // RPCInfo contains RPC information needed by a ConfigSelector.
    51  type RPCInfo struct {
    52  	// Context is the user's context for the RPC and contains headers and
    53  	// application timeout.  It is passed for interception purposes and for
    54  	// efficiency reasons.  SelectConfig should not be blocking.
    55  	Context context.Context
    56  	Method  string // i.e. "/Service/Method"
    57  }
    58  
    59  // RPCConfig describes the configuration to use for each RPC.
    60  type RPCConfig struct {
    61  	// The context to use for the remainder of the RPC; can pass info to LB
    62  	// policy or affect timeout or metadata.
    63  	Context      context.Context
    64  	MethodConfig serviceconfig.MethodConfig // configuration to use for this RPC
    65  	OnCommitted  func()                     // Called when the RPC has been committed (retries no longer possible)
    66  	Interceptor  ClientInterceptor
    67  }
    68  
    69  // ClientStream is the same as grpc.ClientStream, but defined here for circular
    70  // dependency reasons.
    71  type ClientStream interface {
    72  	// Header returns the header metadata received from the server if there
    73  	// is any. It blocks if the metadata is not ready to read.
    74  	Header() (metadata.MD, error)
    75  	// Trailer returns the trailer metadata from the server, if there is any.
    76  	// It must only be called after stream.CloseAndRecv has returned, or
    77  	// stream.Recv has returned a non-nil error (including io.EOF).
    78  	Trailer() metadata.MD
    79  	// CloseSend closes the send direction of the stream. It closes the stream
    80  	// when non-nil error is met. It is also not safe to call CloseSend
    81  	// concurrently with SendMsg.
    82  	CloseSend() error
    83  	// Context returns the context for this stream.
    84  	//
    85  	// It should not be called until after Header or RecvMsg has returned. Once
    86  	// called, subsequent client-side retries are disabled.
    87  	Context() context.Context
    88  	// SendMsg is generally called by generated code. On error, SendMsg aborts
    89  	// the stream. If the error was generated by the client, the status is
    90  	// returned directly; otherwise, io.EOF is returned and the status of
    91  	// the stream may be discovered using RecvMsg.
    92  	//
    93  	// SendMsg blocks until:
    94  	//   - There is sufficient flow control to schedule m with the transport, or
    95  	//   - The stream is done, or
    96  	//   - The stream breaks.
    97  	//
    98  	// SendMsg does not wait until the message is received by the server. An
    99  	// untimely stream closure may result in lost messages. To ensure delivery,
   100  	// users should ensure the RPC completed successfully using RecvMsg.
   101  	//
   102  	// It is safe to have a goroutine calling SendMsg and another goroutine
   103  	// calling RecvMsg on the same stream at the same time, but it is not safe
   104  	// to call SendMsg on the same stream in different goroutines. It is also
   105  	// not safe to call CloseSend concurrently with SendMsg.
   106  	SendMsg(m interface{}) error
   107  	// RecvMsg blocks until it receives a message into m or the stream is
   108  	// done. It returns io.EOF when the stream completes successfully. On
   109  	// any other error, the stream is aborted and the error contains the RPC
   110  	// status.
   111  	//
   112  	// It is safe to have a goroutine calling SendMsg and another goroutine
   113  	// calling RecvMsg on the same stream at the same time, but it is not
   114  	// safe to call RecvMsg on the same stream in different goroutines.
   115  	RecvMsg(m interface{}) error
   116  }
   117  
   118  // ClientInterceptor is an interceptor for gRPC client streams.
   119  type ClientInterceptor interface {
   120  	// NewStream produces a ClientStream for an RPC which may optionally use
   121  	// the provided function to produce a stream for delegation.  Note:
   122  	// RPCInfo.Context should not be used (will be nil).
   123  	//
   124  	// done is invoked when the RPC is finished using its connection, or could
   125  	// not be assigned a connection.  RPC operations may still occur on
   126  	// ClientStream after done is called, since the interceptor is invoked by
   127  	// application-layer operations.  done must never be nil when called.
   128  	NewStream(ctx context.Context, ri RPCInfo, done func(), newStream func(ctx context.Context, done func()) (ClientStream, error)) (ClientStream, error)
   129  }
   130  
   131  // ServerInterceptor is an interceptor for incoming RPC's on gRPC server side.
   132  type ServerInterceptor interface {
   133  	// AllowRPC checks if an incoming RPC is allowed to proceed based on
   134  	// information about connection RPC was received on, and HTTP Headers. This
   135  	// information will be piped into context.
   136  	AllowRPC(ctx context.Context) error // TODO: Make this a real interceptor for filters such as rate limiting.
   137  }
   138  
   139  type csKeyType string
   140  
   141  const csKey = csKeyType("grpc.internal.resolver.configSelector")
   142  
   143  // SetConfigSelector sets the config selector in state and returns the new
   144  // state.
   145  func SetConfigSelector(state resolver.State, cs ConfigSelector) resolver.State {
   146  	state.Attributes = state.Attributes.WithValue(csKey, cs)
   147  	return state
   148  }
   149  
   150  // GetConfigSelector retrieves the config selector from state, if present, and
   151  // returns it or nil if absent.
   152  func GetConfigSelector(state resolver.State) ConfigSelector {
   153  	cs, _ := state.Attributes.Value(csKey).(ConfigSelector)
   154  	return cs
   155  }
   156  
   157  // SafeConfigSelector allows for safe switching of ConfigSelector
   158  // implementations such that previous values are guaranteed to not be in use
   159  // when UpdateConfigSelector returns.
   160  type SafeConfigSelector struct {
   161  	mu sync.RWMutex
   162  	cs ConfigSelector
   163  }
   164  
   165  // UpdateConfigSelector swaps to the provided ConfigSelector and blocks until
   166  // all uses of the previous ConfigSelector have completed.
   167  func (scs *SafeConfigSelector) UpdateConfigSelector(cs ConfigSelector) {
   168  	scs.mu.Lock()
   169  	defer scs.mu.Unlock()
   170  	scs.cs = cs
   171  }
   172  
   173  // SelectConfig defers to the current ConfigSelector in scs.
   174  func (scs *SafeConfigSelector) SelectConfig(r RPCInfo) (*RPCConfig, error) {
   175  	scs.mu.RLock()
   176  	defer scs.mu.RUnlock()
   177  	return scs.cs.SelectConfig(r)
   178  }