@@ -67,13 +67,18 @@ void TDynamicNodeResolverBase::Handle(TEvNodeBroker::TEvResolvedNode::TPtr &ev,
6767
6868 if (rec.GetStatus ().GetCode () != NKikimrNodeBroker::TStatus::OK) {
6969 // Reset proxy if node expired.
70- if (exists)
70+ if (exists) {
7171 ResetInterconnectProxyConfig (NodeId, ctx);
72+ ListNodesCache->Invalidate (); // node was erased
73+ }
7274 ReplyWithErrorAndDie (ctx);
7375 return ;
7476 }
7577
7678 TDynamicConfig::TDynamicNodeInfo node (rec.GetNode ());
79+ if (!exists || !oldNode.EqualExceptExpire (node)) {
80+ ListNodesCache->Invalidate ();
81+ }
7782
7883 // If ID is re-used by another node then proxy has to be reset.
7984 if (exists && !oldNode.EqualExceptExpire (node))
@@ -146,6 +151,7 @@ void TDynamicNameserver::Handle(TEvNodeWardenStorageConfig::TPtr ev) {
146151 auto newStaticConfig = BuildNameserverTable (config);
147152 if (StaticConfig->StaticNodeTable != newStaticConfig->StaticNodeTable ) {
148153 StaticConfig = std::move (newStaticConfig);
154+ ListNodesCache->Invalidate ();
149155 for (const auto & subscriber : StaticNodeChangeSubscribers) {
150156 TActivationContext::Send (new IEventHandle (SelfId (), subscriber, new TEvInterconnect::TEvListNodes));
151157 }
@@ -221,31 +227,40 @@ void TDynamicNameserver::ResolveDynamicNode(ui32 nodeId,
221227 reply->NodeId = nodeId;
222228 ctx.Send (ev->Sender , reply);
223229 } else {
224- ctx.RegisterWithSameMailbox (new TDynamicNodeResolver (SelfId (), nodeId, DynamicConfigs[domain], ev, deadline));
230+ ctx.RegisterWithSameMailbox (new TDynamicNodeResolver (SelfId (), nodeId, DynamicConfigs[domain],
231+ ListNodesCache, ev, deadline));
225232 }
226233}
227234
228235void TDynamicNameserver::SendNodesList (const TActorContext &ctx)
229- {
236+ {
230237 auto now = ctx.Now ();
231- for (auto &sender : ListNodesQueue) {
232- THolder<TEvInterconnect::TEvNodesInfo> reply (new TEvInterconnect::TEvNodesInfo);
238+ if (ListNodesCache->NeedUpdate (now)) {
239+ auto newNodes = MakeIntrusive<TIntrusiveVector<TEvInterconnect::TNodeInfo>>();
240+ auto newExpire = now;
241+
233242 for (const auto &pr : StaticConfig->StaticNodeTable ) {
234- reply-> Nodes . emplace_back (pr.first ,
235- pr.second .Address , pr.second .Host , pr.second .ResolveHost ,
236- pr.second .Port , pr.second .Location , true );
243+ newNodes-> emplace_back (pr.first ,
244+ pr.second .Address , pr.second .Host , pr.second .ResolveHost ,
245+ pr.second .Port , pr.second .Location , true );
237246 }
238247
239248 for (auto &config : DynamicConfigs) {
240249 for (auto &pr : config->DynamicNodes ) {
241- if (pr.second .Expire > now)
242- reply->Nodes .emplace_back (pr.first , pr.second .Address ,
243- pr.second .Host , pr.second .ResolveHost ,
244- pr.second .Port , pr.second .Location , false );
250+ if (pr.second .Expire > now) {
251+ newNodes->emplace_back (pr.first , pr.second .Address ,
252+ pr.second .Host , pr.second .ResolveHost ,
253+ pr.second .Port , pr.second .Location , false );
254+ newExpire = std::min (newExpire, pr.second .Expire );
255+ }
245256 }
246257 }
247258
248- ctx.Send (sender, reply.Release ());
259+ ListNodesCache->Update (newNodes, newExpire);
260+ }
261+
262+ for (auto &sender : ListNodesQueue) {
263+ ctx.Send (sender, new TEvInterconnect::TEvNodesInfo (ListNodesCache->GetNodes ()));
249264 }
250265 ListNodesQueue.clear ();
251266}
@@ -301,15 +316,18 @@ void TDynamicNameserver::UpdateState(const NKikimrNodeBroker::TNodesInfo &rec,
301316 config->ExpiredNodes .emplace (node.GetNodeId (), info);
302317 }
303318
319+ ListNodesCache->Invalidate ();
304320 config->Epoch = rec.GetEpoch ();
305321 ctx.Schedule (config->Epoch .End - ctx.Now (),
306322 new TEvPrivate::TEvUpdateEpoch (domain, config->Epoch .Id + 1 ));
307323 } else {
308324 // Note: this update may be optimized to only include new nodes
309325 for (auto &node : rec.GetNodes ()) {
310326 auto nodeId = node.GetNodeId ();
311- if (!config->DynamicNodes .contains (nodeId))
327+ if (!config->DynamicNodes .contains (nodeId)) {
312328 config->DynamicNodes .emplace (nodeId, node);
329+ ListNodesCache->Invalidate ();
330+ }
313331 }
314332 config->Epoch = rec.GetEpoch ();
315333 }
@@ -396,8 +414,8 @@ void TDynamicNameserver::Handle(TEvInterconnect::TEvGetNode::TPtr &ev, const TAc
396414 ctx.Send (ev->Sender , reply.Release ());
397415 } else {
398416 const TInstant deadline = ev->Get ()->Deadline ;
399- ctx.RegisterWithSameMailbox (new TDynamicNodeSearcher (SelfId (), nodeId, DynamicConfigs[domain], ev. Release (),
400- deadline));
417+ ctx.RegisterWithSameMailbox (new TDynamicNodeSearcher (SelfId (), nodeId, DynamicConfigs[domain],
418+ ListNodesCache, ev. Release (), deadline));
401419 }
402420 }
403421}
@@ -456,6 +474,7 @@ void TDynamicNameserver::Handle(NConsole::TEvConsole::TEvConfigNotificationReque
456474 auto newStaticConfig = BuildNameserverTable (config.GetNameserviceConfig ());
457475 if (StaticConfig->StaticNodeTable != newStaticConfig->StaticNodeTable ) {
458476 StaticConfig = std::move (newStaticConfig);
477+ ListNodesCache->Invalidate ();
459478 for (const auto & subscriber : StaticNodeChangeSubscribers) {
460479 TActivationContext::Send (new IEventHandle (SelfId (), subscriber, new TEvInterconnect::TEvListNodes));
461480 }
@@ -507,5 +526,29 @@ TIntrusivePtr<TTableNameserverSetup> BuildNameserverTable(const NKikimrBlobStora
507526 return table;
508527}
509528
529+ TListNodesCache::TListNodesCache ()
530+ : Nodes(nullptr )
531+ , Expire(TInstant::Zero())
532+ {}
533+
534+
535+ void TListNodesCache::Update (TIntrusiveVector<TEvInterconnect::TNodeInfo>::TConstPtr newNodes, TInstant newExpire) {
536+ Nodes = newNodes;
537+ Expire = newExpire;
538+ }
539+
540+ void TListNodesCache::Invalidate () {
541+ Nodes = nullptr ;
542+ Expire = TInstant::Zero ();
543+ }
544+
545+ bool TListNodesCache::NeedUpdate (TInstant now) const {
546+ return Nodes == nullptr || now > Expire;
547+ }
548+
549+ TIntrusiveVector<TEvInterconnect::TNodeInfo>::TConstPtr TListNodesCache::GetNodes () const {
550+ return Nodes;
551+ }
552+
510553} // NNodeBroker
511554} // NKikimr
0 commit comments