Skip to content
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
6dcb8de
Add cluster factory interface and implementation for the existing clu…
HenryYYang Feb 18, 2019
1ac5471
Add configurable factory
HenryYYang Feb 20, 2019
b4253c2
Fix format issues
HenryYYang Feb 20, 2019
3e056bb
make cluster type oneof
HenryYYang Feb 21, 2019
f5420ee
Fix format error.
HenryYYang Feb 21, 2019
d3a9004
Add integration tests
HenryYYang Feb 27, 2019
759e505
Updated comments and docs.
HenryYYang Feb 27, 2019
789316a
Merge branch 'master' into add-cluster-extension
HenryYYang Feb 28, 2019
e7b1625
Merge remote-tracking branch 'origin' into add-cluster-extension
HenryYYang Feb 28, 2019
ef1f54a
remove TestBase from new tests
HenryYYang Feb 28, 2019
cb3e0eb
Merge branch 'add-cluster-extension' of github.com:HenryYYang/envoy i…
HenryYYang Feb 28, 2019
35b2c86
fix formatting
HenryYYang Feb 28, 2019
b3c41e2
fix formatting
HenryYYang Feb 28, 2019
a5e19da
fix formatting
HenryYYang Feb 28, 2019
5311662
fix clang tidy
HenryYYang Feb 28, 2019
6634824
fix typo
HenryYYang Feb 28, 2019
587b1d0
fix clang-tidy
HenryYYang Feb 28, 2019
ff123bf
Merge branch 'master' of github.com:envoyproxy/envoy into add-cluster…
HenryYYang Feb 28, 2019
d16d0b9
delete deprecated api
HenryYYang Mar 1, 2019
b82e014
Fix PR feedbacks
HenryYYang Mar 2, 2019
0cf38a8
Fix PR feedbacks
HenryYYang Mar 4, 2019
506f51b
Merge branch 'master' into add-cluster-extension
HenryYYang Mar 4, 2019
f75d362
Remove TestBase
HenryYYang Mar 5, 2019
d51e41a
Fix PR feedbacks
HenryYYang Mar 5, 2019
6ccc257
Fix missing import
HenryYYang Mar 5, 2019
0cb3806
Fix duplicate registration
HenryYYang Mar 6, 2019
1716d48
Split implementation and registration of custom static cluster out of…
HenryYYang Mar 6, 2019
735524d
fix format
HenryYYang Mar 6, 2019
b06aca8
remove CUSTOM_CLUSTER_CONFIG
HenryYYang Mar 7, 2019
0a53ccb
Kick CI
HenryYYang Mar 8, 2019
661875e
Merge branch 'master' into add-redis-cluster
HenryYYang Mar 8, 2019
72acffa
Add redis cluster
HenryYYang Mar 26, 2019
fe83017
Add redis cluster test
HenryYYang Mar 31, 2019
b25de9f
Support ipv6
HenryYYang Mar 31, 2019
e95f67e
add version history
HenryYYang Apr 1, 2019
f51b36a
Merge branch 'master' into add-redis-cluster
HenryYYang Apr 1, 2019
c186184
Kick CI
HenryYYang Apr 3, 2019
a30136b
Merge branch 'master' into add-redis-cluster
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 5, 2019
8027e1e
docs
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 8, 2019
e42cac4
Merge branch 'master' into add-redis-cluster
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 8, 2019
dabacd1
make docs work zomg
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 8, 2019
9a8c5ff
fix compile error
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 10, 2019
d2c4606
mitch comments
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 10, 2019
96bbf69
fix issue
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 10, 2019
6738ca9
extra protection on cancels
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 10, 2019
385a6a5
Revert "extra protection on cancels"
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 11, 2019
ae24a89
respond to mitch and matt comments
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 11, 2019
e20db9a
fix spelling
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 11, 2019
354d635
Merge branch 'master' into add-redis-cluster
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 11, 2019
6535c6e
Merge branch 'master' into add-redis-cluster
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 12, 2019
1bb84fb
Update docs per matt comments, put a function in an anonymous namespace
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 12, 2019
d0d73bb
add test for cluster factory exception pass and fail cases
FAYiEKcbD0XFqF2QK2E4viAHg8rMm2VbjYKdjTg Apr 15, 2019
098ccd2
Add integration test
HenryYYang Apr 25, 2019
7a2eb43
Merge branch 'add-redis-cluster' of github.com:HenryYYang/envoy into …
HenryYYang Apr 25, 2019
c35d0b5
Merge branch 'master' into add-redis-cluster
HenryYYang Apr 25, 2019
97f16fe
Fix merge issues
HenryYYang Apr 26, 2019
169fe5d
Fix clang_tidy errors
HenryYYang Apr 26, 2019
71209e2
Add more robust error checking.
HenryYYang Apr 29, 2019
dab3be9
Add more test for cluster slots response
HenryYYang May 2, 2019
3f1bc38
delete twemproxy from dictionary
HenryYYang May 2, 2019
569b693
Small refactor of the RedisCluster class
HenryYYang May 2, 2019
152e1ab
Merge branch 'master' into add-redis-cluster
HenryYYang May 2, 2019
f746acf
Fix code review feedbacks
HenryYYang May 2, 2019
db280e3
Fix code review feedback.
HenryYYang May 3, 2019
710c915
Fix redis cluster test
HenryYYang May 3, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/envoy/config/cluster/redis/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
load("@envoy_api//bazel:api_build_system.bzl", "api_proto_library_internal")

licenses(["notice"]) # Apache 2

api_proto_library_internal(
name = "redis_cluster",
srcs = ["redis_cluster.proto"],
)
22 changes: 22 additions & 0 deletions api/envoy/config/cluster/redis/redis_cluster.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
syntax = "proto3";

package envoy.config.cluster.redis;

option java_outer_classname = "RedisClusterProto";
option java_multiple_files = true;
option java_package = "io.envoyproxy.envoy.config.cluster.redis";
option go_package = "v2";

import "google/protobuf/duration.proto";

import "validate/validate.proto";
import "gogoproto/gogo.proto";

message RedisClusterConfig {
Comment thread
mattklein123 marked this conversation as resolved.
Outdated

Comment thread
mattklein123 marked this conversation as resolved.
Outdated
google.protobuf.Duration cluster_refresh_rate = 1
[(validate.rules).duration.gt = {}, (gogoproto.stdduration) = true];

google.protobuf.Duration cluster_refresh_timeout = 2
[(validate.rules).duration.gt = {}, (gogoproto.stdduration) = true];
}
1 change: 1 addition & 0 deletions docs/root/intro/version_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Version history
* redis: added :ref:`latency stats <config_network_filters_redis_proxy_per_command_stats>` for commands.
* redis: added :ref:`success and error stats <config_network_filters_redis_proxy_per_command_stats>` for commands.
* redis: migrate hash function for host selection to `MurmurHash2 <https://sites.google.com/site/murmurhash>`_ from std::hash. MurmurHash2 is compatible with std::hash in GNU libstdc++ 3.4.20 or above. This is typically the case when compiled on Linux and not macOS.
* redis: added support for Redis cluster custom cluster type.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please merge master and move this into the 1.11.0 section. Also please ref link to the docs.

* router: added ability to configure a :ref:`retry policy <envoy_api_msg_route.RetryPolicy>` at the
virtual host level.
* router: added reset reason to response body when upstream reset happens. After this change, the response body will be of the form `upstream connect error or disconnect/reset before headers. reset reason:`
Expand Down
40 changes: 40 additions & 0 deletions source/extensions/clusters/redis/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
licenses(["notice"]) # Apache 2

load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_package",
)

envoy_package()

envoy_cc_library(
name = "redis_cluster",
srcs = [
"redis_cluster.cc",
"redis_cluster.h",
],
deps = [
"//include/envoy/api:api_interface",
"//include/envoy/http:codec_interface",
"//include/envoy/upstream:cluster_factory_interface",
"//include/envoy/upstream:cluster_manager_interface",
"//include/envoy/upstream:upstream_interface",
"//source/common/config:metadata_lib",
"//source/common/event:dispatcher_lib",
"//source/common/json:config_schemas_lib",
"//source/common/json:json_loader_lib",
"//source/common/network:utility_lib",
"//source/common/singleton:manager_impl_lib",
"//source/common/upstream:cluster_factory_lib",
"//source/common/upstream:upstream_includes",
"//source/common/upstream:upstream_lib",
"//source/extensions/clusters:well_known_names",
"//source/extensions/filters/network/common/redis:client_interface",
"//source/extensions/filters/network/common/redis:client_lib",
"//source/extensions/filters/network/common/redis:codec_interface",
"//source/extensions/transport_sockets/raw_buffer:config",
"//source/server:transport_socket_config_lib",
"@envoy_api//envoy/config/cluster/redis:redis_cluster_cc",
],
)
282 changes: 282 additions & 0 deletions source/extensions/clusters/redis/redis_cluster.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
#include "redis_cluster.h"

namespace Envoy {
namespace Extensions {
namespace Clusters {
namespace Redis {

RedisCluster::RedisCluster(
const envoy::api::v2::Cluster& cluster,
const envoy::config::cluster::redis::RedisClusterConfig& redisCluster,
NetworkFilters::Common::Redis::Client::ClientFactory& redis_client_factory,
Upstream::ClusterManager& clusterManager, Runtime::Loader& runtime,
Network::DnsResolverSharedPtr dns_resolver,
Server::Configuration::TransportSocketFactoryContext& factory_context,
Stats::ScopePtr&& stats_scope, bool added_via_api)
: Upstream::BaseDynamicClusterImpl(cluster, runtime, factory_context, std::move(stats_scope),
added_via_api),
cluster_manager_(clusterManager),
cluster_refresh_rate_(std::chrono::milliseconds(
PROTOBUF_GET_MS_OR_DEFAULT(redisCluster, cluster_refresh_rate, 5000))),
cluster_refresh_timeout_(std::chrono::milliseconds(
PROTOBUF_GET_MS_OR_DEFAULT(redisCluster, cluster_refresh_timeout, 3000))),
dispatcher_(factory_context.dispatcher()), dns_resolver_(std::move(dns_resolver)),
load_assignment_(cluster.has_load_assignment()
? cluster.load_assignment()
: Config::Utility::translateClusterHosts(cluster.hosts())),
local_info_(factory_context.localInfo()), random_(factory_context.random()),
redis_discovery_session_(
std::make_unique<RedisDiscoverySession>(*this, redis_client_factory)) {
switch (cluster.dns_lookup_family()) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing you copied this from somewhere. Can you move this into a common utility function somewhere?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears this was indeed copied from somewhere. I'll put it in a utility.

case envoy::api::v2::Cluster::V6_ONLY:
dns_lookup_family_ = Network::DnsLookupFamily::V6Only;
break;
case envoy::api::v2::Cluster::V4_ONLY:
dns_lookup_family_ = Network::DnsLookupFamily::V4Only;
break;
case envoy::api::v2::Cluster::AUTO:
dns_lookup_family_ = Network::DnsLookupFamily::Auto;
break;
default:
NOT_REACHED_GCOVR_EXCL_LINE;
}

const auto& locality_lb_endpoints = load_assignment_.endpoints();
for (const auto& locality_lb_endpoint : locality_lb_endpoints) {
for (const auto& lb_endpoint : locality_lb_endpoint.lb_endpoints()) {
const auto& host = lb_endpoint.endpoint().address();
dns_discovery_resolve_targets_.emplace_back(new DnsDiscoveryResolveTarget(
Comment thread
mattklein123 marked this conversation as resolved.
*this, host.socket_address().address(), locality_lb_endpoint, lb_endpoint));
}
}
};

void RedisCluster::startPreInit() {
for (const DnsDiscoveryResolveTargetPtr& target : dns_discovery_resolve_targets_) {
target->startResolve();
}
}

void RedisCluster::updateAllHosts(const Upstream::HostVector& hosts_added,
const Upstream::HostVector& hosts_removed,
uint32_t current_priority) {
Upstream::PriorityStateManager priority_state_manager(*this, local_info_, nullptr);
Comment thread
mattklein123 marked this conversation as resolved.

priority_state_manager.initializePriorityFor(redis_discovery_session_->locality_lb_endpoint_);
for (const Upstream::HostSharedPtr& host : redis_discovery_session_->hosts_) {
if (redis_discovery_session_->locality_lb_endpoint_.priority() == current_priority) {
priority_state_manager.registerHostForPriority(
host, redis_discovery_session_->locality_lb_endpoint_);
}
}

priority_state_manager.updateClusterPrioritySet(
current_priority, std::move(priority_state_manager.priorityState()[current_priority].first),
hosts_added, hosts_removed, absl::nullopt);
}

// DnsDiscoveryResolveTarget
RedisCluster::DnsDiscoveryResolveTarget::DnsDiscoveryResolveTarget(
RedisCluster& parent, const std::string& dns_address,
const envoy::api::v2::endpoint::LocalityLbEndpoints& locality_lb_endpoint,
const envoy::api::v2::endpoint::LbEndpoint& lb_endpoint)
: parent_(parent), dns_address_(dns_address), locality_lb_endpoint_(locality_lb_endpoint),
lb_endpoint_(lb_endpoint) {}

RedisCluster::DnsDiscoveryResolveTarget::~DnsDiscoveryResolveTarget() {
if (active_query_) {
active_query_->cancel();
}
}

void RedisCluster::DnsDiscoveryResolveTarget::startResolve() {
ENVOY_LOG(trace, "starting async DNS resolution for {}", dns_address_);

active_query_ = parent_.dns_resolver_->resolve(
dns_address_, parent_.dns_lookup_family_,
[this](const std::list<Network::Address::InstanceConstSharedPtr>&& address_list) -> void {
active_query_ = nullptr;
ENVOY_LOG(trace, "async DNS resolution complete for {}", dns_address_);
parent_.redis_discovery_session_->registerDiscoveryAddress(address_list);
parent_.redis_discovery_session_->startResolve();
});
}

// RedisCluster
RedisCluster::RedisDiscoverySession::RedisDiscoverySession(
Envoy::Extensions::Clusters::Redis::RedisCluster& parent,
NetworkFilters::Common::Redis::Client::ClientFactory& client_factory)
: parent_(parent),
resolve_timer_(parent.dispatcher_.createTimer([this]() -> void { startResolve(); })),
client_factory_(client_factory) {}

inline Network::Address::InstanceConstSharedPtr
Comment thread
mattklein123 marked this conversation as resolved.
Outdated
ProcessCluster(const NetworkFilters::Common::Redis::RespValue& value) {
ASSERT(value.type() == NetworkFilters::Common::Redis::RespType::Array);
Comment thread
HenryYYang marked this conversation as resolved.
Outdated
ASSERT(value.asArray().size() >= 2);
std::string address = value.asArray()[0].asString();
bool ipv6 = (address.find(":") != std::string::npos);
if (ipv6) {
return std::make_shared<Network::Address::Ipv6Instance>(address,
value.asArray()[1].asInteger());
}
return std::make_shared<Network::Address::Ipv4Instance>(address, value.asArray()[1].asInteger());
}

RedisCluster::RedisDiscoverySession::~RedisDiscoverySession() {
if (current_request_) {
current_request_->cancel();
current_request_ = nullptr;
}

if (client_) {
client_->close();
}
}

void RedisCluster::RedisDiscoverySession::onEvent(Network::ConnectionEvent event) {
if (event == Network::ConnectionEvent::RemoteClose ||
event == Network::ConnectionEvent::LocalClose) {
// This should only happen after any active requests have been failed/cancelled.
Comment thread
mattklein123 marked this conversation as resolved.
Outdated
ASSERT(!current_request_);
parent_.dispatcher_.deferredDelete(std::move(client_));
}
}

void RedisCluster::RedisDiscoverySession::registerDiscoveryAddress(
const std::list<Envoy::Network::Address::InstanceConstSharedPtr>& address_list) {
absl::MutexLock l(&discovery_mutex_);
discovery_address_list_.insert(discovery_address_list_.end(), address_list.begin(),
address_list.end());
}

void RedisCluster::RedisDiscoverySession::startResolve() {
absl::MutexLock l(&discovery_mutex_);
parent_.info_->stats().update_attempt_.inc();
// if a resolution is current in progress, skip
Comment thread
mattklein123 marked this conversation as resolved.
Outdated
if (current_request_) {
return;
}

// if hosts is empty, we haven't got a successful result from CLUSTER SLOTS call yet, pick a
// random discovery address from dns
Upstream::HostSharedPtr host;
if (hosts_.empty()) {
const int rand_idx = parent_.random_.random() % discovery_address_list_.size();
auto it = discovery_address_list_.begin();
std::next(it, rand_idx);
host = Upstream::HostSharedPtr{new RedisHost(parent_.info(), "", *it, parent_, true)};
} else {
const int rand_idx = parent_.random_.random() % hosts_.size();
host = hosts_[rand_idx];
}

if (!client_) {
client_ = client_factory_.create(host, parent_.dispatcher_, *this);
client_->addConnectionCallbacks(*this);
}

current_request_ = client_->makeRequest(ClusterSlotsRequest::instance_, *this);
}

void RedisCluster::RedisDiscoverySession::onResponse(
NetworkFilters::Common::Redis::RespValuePtr&& value) {
absl::MutexLock l(&discovery_mutex_);

current_request_ = nullptr;
// TODO(hyang): move to use connection pool for the cluster and avoid closing the connection each
// time
if (client_) {
Comment thread
mattklein123 marked this conversation as resolved.
Outdated
client_->close();
}

if (value->type() != NetworkFilters::Common::Redis::RespType::Array) {
ENVOY_LOG(error, "Unexpected response to cluster slot command: {}", value->toString());
Comment thread
mattklein123 marked this conversation as resolved.
Outdated
parent_.info_->stats().update_no_rebuild_.inc();
return;
}

Upstream::HostVector new_hosts;
std::array<std::string, 16384> slots_;
Comment thread
mattklein123 marked this conversation as resolved.
Outdated

for (const NetworkFilters::Common::Redis::RespValue& part : value->asArray()) {
const std::vector<NetworkFilters::Common::Redis::RespValue>& slotRange = part.asArray();
ASSERT(slotRange.size() >= 3);
Comment thread
mattklein123 marked this conversation as resolved.
Outdated

// field 0: start slot range
auto startField = slotRange[0].asInteger();

// field 1: end slot range
auto endField = slotRange[1].asInteger();

// field 2: master address for slot range
// TODO(hyang): for now we're only adding the master node for each slot, when we're ready to
// send requests to slave nodes, we need to add subsequent address in the response as slave
// nodes
auto masterAddress = ProcessCluster(slotRange[2]);
// add to the slot
for (auto i = startField; i <= endField; ++i) {
slots_[i] = masterAddress->asString();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cluster_slots_map_ std::array() is a flexible approach for handling the slot mapping, but it does seem like it takes up a lot of memory (16384 std::string's) and CPU cycles (as seen here in the copying of 16384 strings over all cluster members) for a map that will generally scale as O(n) where n is the number of cluster nodes. I would suggest creating a // TODO around investigating the performance of alternative representations.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Henry and I discussed this at length; we felt it was an acceptable mode of behavior for now but did not that this may not be ideal! I'll add a todo.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to explain this mapping somewhere, maybe on the class comment? As someone that doesn't understand the protocol I think a brief description would be useful? I'm not sure what the tradeoffs here are.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do

}
new_hosts.emplace_back(
new RedisHost(parent_.info(), "", std::move(masterAddress), parent_, true));
}

std::unordered_map<std::string, Upstream::HostSharedPtr> updated_hosts;
Upstream::HostVector hosts_added;
Upstream::HostVector hosts_removed;
if (parent_.updateDynamicHostList(new_hosts, hosts_, hosts_added, hosts_removed, updated_hosts,
all_hosts_)) {
ASSERT(std::all_of(hosts_.begin(), hosts_.end(), [&](const auto& host) {
return host->priority() == locality_lb_endpoint_.priority();
}));
parent_.updateAllHosts(hosts_added, hosts_removed, locality_lb_endpoint_.priority());
} else {
parent_.info_->stats().update_no_rebuild_.inc();
}

all_hosts_ = std::move(updated_hosts);
cluster_slots_map_.swap(slots_);

// If there is an initialize callback, fire it now. Note that if the cluster refers to
// multiple DNS names, this will return initialized after a single DNS resolution
// completes. This is not perfect but is easier to code and unclear if the extra
// complexity is needed so will start with this.
parent_.onPreInitComplete();
resolve_timer_->enableTimer(parent_.cluster_refresh_rate_);
}

void RedisCluster::RedisDiscoverySession::onFailure() {
absl::MutexLock l(&discovery_mutex_);
current_request_ = nullptr;
if (client_) {
client_->close();
}
parent_.info()->stats().update_failure_.inc();
resolve_timer_->enableTimer(parent_.cluster_refresh_rate_);
}

RedisCluster::ClusterSlotsRequest RedisCluster::ClusterSlotsRequest::instance_;

Upstream::ClusterImplBaseSharedPtr RedisClusterFactory::createClusterWithConfig(
const envoy::api::v2::Cluster& cluster,
const envoy::config::cluster::redis::RedisClusterConfig& proto_config,
Upstream::ClusterFactoryContext& context,
Envoy::Server::Configuration::TransportSocketFactoryContext& socket_factory_context,
Envoy::Stats::ScopePtr&& stats_scope) {
if (!cluster.has_cluster_type() ||
cluster.cluster_type().name() != Extensions::Clusters::ClusterTypes::get().Redis) {
throw EnvoyException("Redis cluster can only created with redis cluster type");
Comment thread
mattklein123 marked this conversation as resolved.
}
return std::make_shared<RedisCluster>(
cluster, proto_config, NetworkFilters::Common::Redis::Client::ClientFactoryImpl::instance_,
context.clusterManager(), context.runtime(), selectDnsResolver(cluster, context),
socket_factory_context, std::move(stats_scope), context.addedViaApi());
}

REGISTER_FACTORY(RedisClusterFactory, Upstream::ClusterFactory);

} // namespace Redis
} // namespace Clusters
} // namespace Extensions
} // namespace Envoy
Loading