1
#pragma once
2

            
3
#include "envoy/config/core/v3/grpc_service.pb.h"
4
#include "envoy/grpc/async_client.h"
5
#include "envoy/stats/scope.h"
6

            
7
namespace Envoy {
8
namespace Grpc {
9

            
10
class AsyncClientFactoryImpl;
11

            
12
// Per-service factory for Grpc::RawAsyncClients. This factory is thread aware and will instantiate
13
// with thread local state. Clients will use ThreadLocal::Instance::dispatcher() for event handling.
14
class AsyncClientFactory {
15
public:
16
2893
  virtual ~AsyncClientFactory() = default;
17

            
18
  /**
19
   * Create a gRPC::RawAsyncClient.
20
   * Prefer AsyncClientManager::getOrCreateRawAsyncClient() to creating uncached raw async client
21
   * from factory directly. Only call this method when the raw async client must be owned
22
   * exclusively. For example, some filters pass *this reference to raw client. In this case, the
23
   * client must be destroyed before the filter instance. In this case, the grpc client must be
24
   * owned by the filter instance exclusively.
25
   * @return RawAsyncClientPtr async client or an error status.
26
   */
27
  virtual absl::StatusOr<RawAsyncClientPtr> createUncachedRawAsyncClient() PURE;
28

            
29
private:
30
  friend class AsyncClientFactoryImpl;
31
};
32

            
33
using AsyncClientFactoryPtr = std::unique_ptr<AsyncClientFactory>;
34

            
35
class GrpcServiceConfigWithHashKey {
36
public:
37
177
  GrpcServiceConfigWithHashKey() = default;
38

            
39
  explicit GrpcServiceConfigWithHashKey(const envoy::config::core::v3::GrpcService& config)
40
2015
      : config_(config), pre_computed_hash_(Envoy::MessageUtil::hash(config)) {};
41

            
42
375
  template <typename H> friend H AbslHashValue(H h, const GrpcServiceConfigWithHashKey& wrapper) {
43
375
    return H::combine(std::move(h), wrapper.pre_computed_hash_);
44
375
  }
45

            
46
4
  std::size_t getPreComputedHash() const { return pre_computed_hash_; }
47

            
48
  friend bool operator==(const GrpcServiceConfigWithHashKey& lhs,
49
691
                         const GrpcServiceConfigWithHashKey& rhs) {
50
691
    if (lhs.pre_computed_hash_ == rhs.pre_computed_hash_) {
51
660
      return Protobuf::util::MessageDifferencer::Equivalent(lhs.config_, rhs.config_);
52
660
    }
53
31
    return false;
54
691
  }
55

            
56
855
  const envoy::config::core::v3::GrpcService& config() const { return config_; }
57

            
58
22
  void setConfig(const envoy::config::core::v3::GrpcService& g) {
59
22
    config_ = g;
60
22
    pre_computed_hash_ = Envoy::MessageUtil::hash(g);
61
22
  }
62

            
63
private:
64
  envoy::config::core::v3::GrpcService config_;
65
  std::size_t pre_computed_hash_;
66
};
67

            
68
// Singleton gRPC client manager. Grpc::AsyncClientManager can be used to create per-service
69
// Grpc::AsyncClientFactory instances. All manufactured Grpc::AsyncClients must
70
// be destroyed before the AsyncClientManager can be safely destructed.
71
class AsyncClientManager {
72
public:
73
54026
  virtual ~AsyncClientManager() = default;
74

            
75
  // TODO(diazalan) deprecate old getOrCreateRawAsyncClient once all filters have been transitioned
76
  /**
77
   * Create a Grpc::RawAsyncClient. The async client is cached thread locally and shared across
78
   * different filter instances.
79
   * @param grpc_service envoy::config::core::v3::GrpcService configuration.
80
   * @param scope stats scope.
81
   * @param skip_cluster_check if set to true skips checks for cluster presence and being statically
82
   * configured.
83
   * @param cache_option always use cache or use cache when runtime is enabled.
84
   * @return RawAsyncClientPtr a grpc async client or an invalid status.
85
   */
86
  virtual absl::StatusOr<RawAsyncClientSharedPtr>
87
  getOrCreateRawAsyncClient(const envoy::config::core::v3::GrpcService& grpc_service,
88
                            Stats::Scope& scope, bool skip_cluster_check) PURE;
89

            
90
  /**
91
   * Create a Grpc::RawAsyncClient. The async client is cached thread locally and shared across
92
   * different filter instances.
93
   * @param grpc_service Envoy::Grpc::GrpcServiceConfigWithHashKey which contains config and
94
   * hashkey.
95
   * @param scope stats scope.
96
   * @param skip_cluster_check if set to true skips checks for cluster presence and being statically
97
   * configured.
98
   * @param cache_option always use cache or use cache when runtime is enabled.
99
   * @return RawAsyncClientPtr a grpc async client.
100
   * @throws EnvoyException when grpc_service validation fails.
101
   */
102
  virtual absl::StatusOr<RawAsyncClientSharedPtr>
103
  getOrCreateRawAsyncClientWithHashKey(const GrpcServiceConfigWithHashKey& grpc_service,
104
                                       Stats::Scope& scope, bool skip_cluster_check) PURE;
105

            
106
  /**
107
   * Create a Grpc::AsyncClients factory for a service. Validation of the service is performed and
108
   * will raise an exception on failure.
109
   * @param grpc_service envoy::config::core::v3::GrpcService configuration.
110
   * @param scope stats scope.
111
   * @param skip_cluster_check if set to true skips checks for cluster presence and being statically
112
   * configured.
113
   * @return AsyncClientFactoryPtr factory for grpc_service or an error status.
114
   */
115
  virtual absl::StatusOr<AsyncClientFactoryPtr>
116
  factoryForGrpcService(const envoy::config::core::v3::GrpcService& grpc_service,
117
                        Stats::Scope& scope, bool skip_cluster_check) PURE;
118
};
119

            
120
using AsyncClientManagerPtr = std::unique_ptr<AsyncClientManager>;
121

            
122
} // namespace Grpc
123
} // namespace Envoy