1 // 2 // Copyright 2015 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef GRPC_SRC_CORE_RESOLVER_RESOLVER_H 18 #define GRPC_SRC_CORE_RESOLVER_RESOLVER_H 19 20 #include <grpc/support/port_platform.h> 21 22 #include <functional> 23 #include <string> 24 25 #include "absl/status/status.h" 26 #include "absl/status/statusor.h" 27 #include "src/core/lib/channel/channel_args.h" 28 #include "src/core/lib/debug/trace.h" 29 #include "src/core/resolver/endpoint_addresses.h" 30 #include "src/core/resolver/server_address.h" // IWYU pragma: keep 31 #include "src/core/service_config/service_config.h" 32 #include "src/core/util/orphanable.h" 33 #include "src/core/util/ref_counted_ptr.h" 34 35 namespace grpc_core { 36 37 /// Interface for name resolution. 38 /// 39 /// This interface is designed to support both push-based and pull-based 40 /// mechanisms. A push-based mechanism is one where the resolver will 41 /// subscribe to updates for a given name, and the name service will 42 /// proactively send new data to the resolver whenever the data associated 43 /// with the name changes. A pull-based mechanism is one where the resolver 44 /// needs to query the name service again to get updated information (e.g., 45 /// DNS). 46 /// 47 /// Note: All methods with a "Locked" suffix must be called from the 48 /// work_serializer passed to the constructor. 49 class Resolver : public InternallyRefCounted<Resolver> { 50 public: 51 /// Results returned by the resolver. 52 struct Result { 53 /// A list of endpoints, each with one or more addresses, or an error. 54 absl::StatusOr<EndpointAddressesList> addresses; 55 /// A service config, or an error. 56 absl::StatusOr<RefCountedPtr<ServiceConfig>> service_config = nullptr; 57 /// An optional human-readable note describing context about the resolution, 58 /// to be passed along to the LB policy for inclusion in RPC failure status 59 /// messages in cases where neither \a addresses nor \a service_config 60 /// has a non-OK status. For example, a resolver that returns an empty 61 /// address list but a valid service config may set to this to something 62 /// like "no DNS entries found for <name>". 63 std::string resolution_note; 64 // TODO(roth): Before making this a public API, figure out a way to 65 // avoid exposing channel args this way. 66 ChannelArgs args; 67 // If non-null, this callback will be invoked when the LB policy has 68 // processed the result. The status value passed to the callback 69 // indicates whether the LB policy accepted the update. For polling 70 // resolvers, if the reported status is non-OK, then the resolver 71 // should put itself into backoff to retry the resolution later. 72 // The resolver impl must not call ResultHandler::ReportResult() 73 // again until after this callback has been invoked. 74 // The callback will be invoked within the channel's WorkSerializer. 75 // It may or may not be invoked before ResultHandler::ReportResult() 76 // returns, which is why it's a separate callback. 77 std::function<void(absl::Status)> result_health_callback; 78 }; 79 80 /// A proxy object used by the resolver to return results to the 81 /// client channel. 82 class ResultHandler { 83 public: ~ResultHandler()84 virtual ~ResultHandler() {} 85 86 /// Reports a result to the channel. 87 virtual void ReportResult(Result result) = 0; // NOLINT 88 }; 89 90 // Not copyable nor movable. 91 Resolver(const Resolver&) = delete; 92 Resolver& operator=(const Resolver&) = delete; 93 ~Resolver() override = default; 94 95 /// Starts resolving. 96 virtual void StartLocked() = 0; 97 98 /// Asks the resolver to obtain an updated resolver result, if 99 /// applicable. 100 /// 101 /// This is useful for pull-based implementations to decide when to 102 /// re-resolve. However, the implementation is not required to 103 /// re-resolve immediately upon receiving this call; it may instead 104 /// elect to delay based on some configured minimum time between 105 /// queries, to avoid hammering the name service with queries. 106 /// 107 /// For push-based implementations, this may be a no-op. 108 /// 109 /// Note: Implementations must not invoke any method on the 110 /// ResultHandler from within this call. RequestReresolutionLocked()111 virtual void RequestReresolutionLocked() {} 112 113 /// Resets the re-resolution backoff, if any. 114 /// This needs to be implemented only by pull-based implementations; 115 /// for push-based implementations, it will be a no-op. ResetBackoffLocked()116 virtual void ResetBackoffLocked() {} 117 118 // Note: This must be invoked while holding the work_serializer. Orphan()119 void Orphan() override { 120 ShutdownLocked(); 121 Unref(); 122 } 123 124 protected: 125 Resolver(); 126 127 /// Shuts down the resolver. 128 virtual void ShutdownLocked() = 0; 129 }; 130 131 } // namespace grpc_core 132 133 #endif // GRPC_SRC_CORE_RESOLVER_RESOLVER_H 134