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 }