github.com/m3db/m3@v1.5.0/src/query/remote/static_resolver.go (about) 1 // Copyright (c) 2018 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 remote 22 23 import ( 24 "fmt" 25 26 "google.golang.org/grpc/resolver" 27 ) 28 29 const ( 30 _staticResolverSchema = "static" 31 // staticResolverURL is the same regardless of which endpoints are being dialed. The expectation 32 // is that callers use grpc.WithResolver on a per grpc.Dial basis in order to get correct routing. 33 _staticResolverURL = _staticResolverSchema + ":///" 34 ) 35 36 // Assert we implement resolver.Builder 37 var _ resolver.Builder = (*staticResolverBuilder)(nil) 38 39 // staticResolverBuilder implements resolver.Builder. 40 // It constructs a staticResolver, which: 41 // - Always routes to a static list of endpoints (never updates) 42 // - Performs round-robin load balancing between them. 43 type staticResolverBuilder struct { 44 addresses []string 45 } 46 47 func newStaticResolverBuilder(addresses []string) *staticResolverBuilder { 48 return &staticResolverBuilder{addresses: addresses} 49 } 50 51 func (b *staticResolverBuilder) Build( 52 target resolver.Target, 53 cc resolver.ClientConn, 54 opts resolver.BuildOptions, 55 ) (resolver.Resolver, error) { 56 addrs := make([]resolver.Address, 0, len(b.addresses)) 57 for _, a := range b.addresses { 58 addrs = append(addrs, resolver.Address{Addr: a}) 59 } 60 r := staticResolver{} 61 62 // N.B.: we are configuring the service config using as described in 63 // https://github.com/grpc/grpc/blob/master/doc/service_config.md. 64 // Technically speaking, this JSON is defined by the proto structure ServiceConfig in: 65 // https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto 66 // However, the grpc-go package doesn't include an exposed, generated version of that protobuf type, 67 // despite the fact that it very clearly relies on a specific version of it (e.g. it would fail if 68 // we had a separate version of the .proto file). 69 // Therefore, follow the example of: 70 // https://github.com/grpc/grpc-go/blob/master/examples/features/load_balancing/client/main.go#L75-L75 71 // and use a static config JSON representation here. 72 const pfc = `{"loadBalancingConfig": [{"round_robin":{}}]}` 73 scpr := cc.ParseServiceConfig(pfc) 74 if scpr.Err != nil { 75 return nil, fmt.Errorf( 76 "failed to parse static service config for GRPC: %w. Config was: %q", 77 scpr.Err, 78 pfc, 79 ) 80 } 81 if err := cc.UpdateState(resolver.State{ 82 Addresses: addrs, 83 ServiceConfig: scpr, 84 }); err != nil { 85 return nil, fmt.Errorf("failed to update connection state while building resolver: %w", err) 86 } 87 return r, nil 88 } 89 90 func (b *staticResolverBuilder) Scheme() string { return _staticResolverSchema } 91 92 var _ resolver.Resolver = staticResolver{} 93 94 // staticResolver implements resolver.Resolver 95 type staticResolver struct{} 96 97 func (r staticResolver) ResolveNow(resolver.ResolveNowOptions) {} 98 99 func (r staticResolver) Close() {}