diff --git a/mcrouter/ProxyConfig-inl.h b/mcrouter/ProxyConfig-inl.h index 9794149c6..f49357547 100644 --- a/mcrouter/ProxyConfig-inl.h +++ b/mcrouter/ProxyConfig-inl.h @@ -107,7 +107,15 @@ ProxyConfig::ProxyConfig( partialConfigs_ = provider.releasePartialConfigs(); } accessPoints_ = provider.releaseAccessPoints(); - proxyRoute_ = std::make_shared>(proxy, routeSelectors); + bool disableBroadcastDeleteRpc = false; + if (auto* jDisableBroadcastDeleteRpc = + json.get_ptr("disable_broadcast_delete_rpc")) { + disableBroadcastDeleteRpc = + parseBool(*jDisableBroadcastDeleteRpc, "disable_broadcast_delete_rpc"); + } + + proxyRoute_ = std::make_shared>( + proxy, routeSelectors, disableBroadcastDeleteRpc); serviceInfo_ = std::make_shared>(proxy, *this); } diff --git a/mcrouter/routes/ProxyRoute-inl.h b/mcrouter/routes/ProxyRoute-inl.h index 5d6a39f7f..92484eaaf 100644 --- a/mcrouter/routes/ProxyRoute-inl.h +++ b/mcrouter/routes/ProxyRoute-inl.h @@ -41,11 +41,13 @@ typename RouterInfo::RouteHandlePtr wrapWithBigValueRoute( template ProxyRoute::ProxyRoute( Proxy& proxy, - const RouteSelectorMap& routeSelectors) + const RouteSelectorMap& routeSelectors, + bool disableBroadcastDeleteRpc) : proxy_(proxy), root_(makeRouteHandle( proxy_, - routeSelectors)) { + routeSelectors, + disableBroadcastDeleteRpc)) { if (proxy_.getRouterOptions().big_value_split_threshold != 0) { root_ = detail::wrapWithBigValueRoute( std::move(root_), proxy_.getRouterOptions()); diff --git a/mcrouter/routes/ProxyRoute.h b/mcrouter/routes/ProxyRoute.h index 990a1d105..46f09eb5e 100644 --- a/mcrouter/routes/ProxyRoute.h +++ b/mcrouter/routes/ProxyRoute.h @@ -43,7 +43,8 @@ class ProxyRoute { ProxyRoute( Proxy& proxy, const RouteSelectorMap& - routeSelectors); + routeSelectors, + bool disableBroadcastDeleteRpc = false); template bool traverse( diff --git a/mcrouter/routes/RootRoute.h b/mcrouter/routes/RootRoute.h index e908c22f8..c4e434a62 100644 --- a/mcrouter/routes/RootRoute.h +++ b/mcrouter/routes/RootRoute.h @@ -35,12 +35,14 @@ class RootRoute { RootRoute( ProxyBase& proxy, - const RouteSelectorMap& routeSelectors) + const RouteSelectorMap& routeSelectors, + bool disableBroadcastDeleteRpc = false) : opts_(proxy.getRouterOptions()), rhMap_( routeSelectors, opts_.default_route, - opts_.send_invalid_route_to_default) {} + opts_.send_invalid_route_to_default), + disableBroadcastDeleteRpc_(disableBroadcastDeleteRpc) {} template bool traverse( @@ -93,6 +95,7 @@ class RootRoute { private: const McrouterOptions& opts_; RouteHandleMap rhMap_; + bool disableBroadcastDeleteRpc_; template ReplyT routeImpl( @@ -148,10 +151,19 @@ class RootRoute { ReplyT doRoute( const std::vector>& rh, const Request& req) const { - if (LIKELY(rh.size() == 1)) { + if (FOLLY_LIKELY(rh.size() == 1)) { return rh[0]->route(req); } if (!rh.empty()) { + // Broadcast delete via Distribution, route only + // to the first (local) route handle + if constexpr (folly::IsOneOf::value) { + if (disableBroadcastDeleteRpc_ && + req.key_ref()->routingPrefix() == kBroadcastPrefix) { + return rh[0]->route(req); + } + } + auto reqCopy = std::make_shared(req); for (size_t i = 1, e = rh.size(); i < e; ++i) { auto r = rh[i]; diff --git a/mcrouter/routes/RouteHandleMap-inl.h b/mcrouter/routes/RouteHandleMap-inl.h index f4d9370f8..7d30f69fa 100644 --- a/mcrouter/routes/RouteHandleMap-inl.h +++ b/mcrouter/routes/RouteHandleMap-inl.h @@ -27,6 +27,7 @@ namespace facebook { namespace memcache { namespace mcrouter { +constexpr std::string_view kBroadcastPrefix = "/*/*/"; constexpr const char* kFallbackCluster = "fallback"; namespace detail { @@ -140,7 +141,7 @@ void RouteHandleMap::foreachRoutePolicy( return; } - bool selectAll = (prefix == "/*/*/"); + bool selectAll = (prefix == kBroadcastPrefix); for (const auto& it : byRoute_) { if (it.first != defaultRoute_.str() && (selectAll || match_pattern_route(prefix, it.first))) { @@ -204,7 +205,7 @@ RouteHandleMap::getTargetsForKeyFast( if (LIKELY(prefix.empty())) { // empty prefix => route to default route result = &defaultRouteMap_->getTargetsForKey(key); - } else if (prefix == "/*/*/") { + } else if (prefix == kBroadcastPrefix) { // route to all routes result = &allRoutes_->getTargetsForKey(key); } else {