2121#include " src/utils/cancel.h"
2222#include " src/valkey_search.h"
2323#include " vmsdk/src/blocked_client.h"
24+ #include " vmsdk/src/cluster_map.h"
2425#include " vmsdk/src/debug.h"
2526#include " vmsdk/src/log.h"
2627#include " vmsdk/src/module_config.h"
@@ -30,7 +31,8 @@ namespace valkey_search::query::fanout {
3031
3132constexpr unsigned kNoValkeyTimeout = 86400000 ;
3233
33- template <typename Request, typename Response, FanoutTargetMode kTargetMode >
34+ template <typename Request, typename Response,
35+ vmsdk::cluster_map::FanoutTargetMode kTargetMode >
3436class FanoutOperationBase {
3537 public:
3638 explicit FanoutOperationBase () = default;
@@ -43,7 +45,19 @@ class FanoutOperationBase {
4345 blocked_client_->MeasureTimeStart ();
4446 deadline_tp_ = std::chrono::steady_clock::now () +
4547 std::chrono::milliseconds (GetTimeoutMs ());
46- targets_ = GetTargets (ctx);
48+
49+ targets_ = GetTargets ();
50+ // If we only got 1 local target, the cluster map is likely stale
51+ // Refresh it to get the full cluster topology
52+ if (targets_.size () == 1 &&
53+ targets_[0 ].location == vmsdk::cluster_map::NodeInfo::kLocal ) {
54+ VMSDK_LOG (NOTICE, ctx)
55+ << " Only 1 local target found in cluster mode, "
56+ << " refreshing cluster map to get full topology..." ;
57+ ValkeySearch::Instance ().RefreshClusterMap (ctx);
58+ VMSDK_LOG (NOTICE, ctx) << " Cluster map refreshed" ;
59+ }
60+
4761 StartFanoutRound ();
4862 }
4963
@@ -77,6 +91,7 @@ class FanoutOperationBase {
7791 }
7892
7993 void StartFanoutRound () {
94+ targets_ = GetTargets ();
8095 outstanding_ = targets_.size ();
8196 unsigned timeout_ms = GetTimeoutMs ();
8297 for (const auto & target : targets_) {
@@ -85,16 +100,14 @@ class FanoutOperationBase {
85100 }
86101 }
87102
88- std::vector<FanoutSearchTarget> GetTargets (ValkeyModuleCtx* ctx) const {
89- return query::fanout::FanoutTemplate::GetTargets (ctx, kTargetMode );
90- }
103+ virtual std::vector<vmsdk::cluster_map::NodeInfo> GetTargets () const = 0;
91104
92- void IssueRpc (const FanoutSearchTarget & target, const Request& request ,
93- unsigned timeout_ms) {
105+ void IssueRpc (const vmsdk::cluster_map::NodeInfo & target,
106+ const Request& request, unsigned timeout_ms) {
94107 coordinator::ClientPool* client_pool_ =
95108 ValkeySearch::Instance ().GetCoordinatorClientPool ();
96109
97- if (target.type == FanoutSearchTarget::Type ::kLocal ) {
110+ if (target.location == vmsdk::cluster_map::NodeInfo ::kLocal ) {
98111 vmsdk::RunByMain ([this , target, request]() {
99112 auto [status, resp] = this ->GetLocalResponse (request, target);
100113 if (status.ok ()) {
@@ -151,7 +164,7 @@ class FanoutOperationBase {
151164 }
152165
153166 virtual std::pair<grpc::Status, Response> GetLocalResponse (
154- const Request&, [[maybe_unused]] const FanoutSearchTarget &) = 0;
167+ const Request&, [[maybe_unused]] const vmsdk::cluster_map::NodeInfo &) = 0;
155168
156169 virtual void InvokeRemoteRpc (coordinator::Client*, const Request&,
157170 std::function<void (grpc::Status, Response&)>,
@@ -160,14 +173,15 @@ class FanoutOperationBase {
160173 virtual unsigned GetTimeoutMs () const = 0;
161174
162175 virtual Request GenerateRequest (
163- [[maybe_unused]] const FanoutSearchTarget &) = 0;
176+ [[maybe_unused]] const vmsdk::cluster_map::NodeInfo &) = 0;
164177
165- virtual void OnResponse (const Response&,
166- [[maybe_unused]] const FanoutSearchTarget&) = 0;
178+ virtual void OnResponse (
179+ const Response&,
180+ [[maybe_unused]] const vmsdk::cluster_map::NodeInfo&) = 0;
167181
168182 virtual void OnError (grpc::Status status,
169183 coordinator::FanoutErrorType error_type,
170- const FanoutSearchTarget & target) {
184+ const vmsdk::cluster_map::NodeInfo & target) {
171185 absl::MutexLock lock (&mutex_);
172186 if (error_type == coordinator::FanoutErrorType::INDEX_NAME_ERROR) {
173187 index_name_error_nodes.push_back (target);
@@ -205,8 +219,9 @@ class FanoutOperationBase {
205219 // Log index name errors
206220 if (!index_name_error_nodes.empty ()) {
207221 error_message = " Index name not found." ;
208- for (const FanoutSearchTarget& target : index_name_error_nodes) {
209- if (target.type == FanoutSearchTarget::Type::kLocal ) {
222+ for (const vmsdk::cluster_map::NodeInfo& target :
223+ index_name_error_nodes) {
224+ if (target.location == vmsdk::cluster_map::NodeInfo::kLocal ) {
210225 VMSDK_LOG_EVERY_N_SEC (WARNING, ctx, 1 )
211226 << INDEX_NAME_ERROR_LOG_PREFIX << " LOCAL NODE" ;
212227 } else {
@@ -218,8 +233,9 @@ class FanoutOperationBase {
218233 // Log communication errors
219234 if (!communication_error_nodes.empty ()) {
220235 error_message = " Communication error between nodes found." ;
221- for (const FanoutSearchTarget& target : communication_error_nodes) {
222- if (target.type == FanoutSearchTarget::Type::kLocal ) {
236+ for (const vmsdk::cluster_map::NodeInfo& target :
237+ communication_error_nodes) {
238+ if (target.location == vmsdk::cluster_map::NodeInfo::kLocal ) {
223239 VMSDK_LOG_EVERY_N_SEC (WARNING, ctx, 1 )
224240 << COMMUNICATION_ERROR_LOG_PREFIX << " LOCAL NODE" ;
225241 } else {
@@ -231,8 +247,9 @@ class FanoutOperationBase {
231247 // Log inconsistent state errors
232248 if (!inconsistent_state_error_nodes.empty ()) {
233249 error_message = " Inconsistent index state error found." ;
234- for (const FanoutSearchTarget& target : inconsistent_state_error_nodes) {
235- if (target.type == FanoutSearchTarget::Type::kLocal ) {
250+ for (const vmsdk::cluster_map::NodeInfo& target :
251+ inconsistent_state_error_nodes) {
252+ if (target.location == vmsdk::cluster_map::NodeInfo::kLocal ) {
236253 VMSDK_LOG_EVERY_N_SEC (WARNING, ctx, 1 )
237254 << INCONSISTENT_STATE_ERROR_LOG_PREFIX << " LOCAL NODE" ;
238255 } else {
@@ -286,10 +303,10 @@ class FanoutOperationBase {
286303 unsigned outstanding_{0 };
287304 absl::Mutex mutex_;
288305 std::unique_ptr<vmsdk::BlockedClient> blocked_client_;
289- std::vector<FanoutSearchTarget > index_name_error_nodes;
290- std::vector<FanoutSearchTarget > inconsistent_state_error_nodes;
291- std::vector<FanoutSearchTarget > communication_error_nodes;
292- std::vector<FanoutSearchTarget > targets_;
306+ std::vector<vmsdk::cluster_map::NodeInfo > index_name_error_nodes;
307+ std::vector<vmsdk::cluster_map::NodeInfo > inconsistent_state_error_nodes;
308+ std::vector<vmsdk::cluster_map::NodeInfo > communication_error_nodes;
309+ std::vector<vmsdk::cluster_map::NodeInfo > targets_;
293310 std::chrono::steady_clock::time_point deadline_tp_;
294311 bool timeout_occurred_ = false ;
295312};
0 commit comments