@@ -66,13 +66,18 @@ void TDynamicNodeResolverBase::Handle(TEvNodeBroker::TEvResolvedNode::TPtr &ev,
6666
6767 if (rec.GetStatus ().GetCode () != NKikimrNodeBroker::TStatus::OK) {
6868 // Reset proxy if node expired.
69- if (exists)
69+ if (exists) {
7070 ResetInterconnectProxyConfig (NodeId, ctx);
71+ ListNodesCache->Invalidate (); // node was erased
72+ }
7173 ReplyWithErrorAndDie (ctx);
7274 return ;
7375 }
7476
7577 TDynamicConfig::TDynamicNodeInfo node (rec.GetNode ());
78+ if (!exists || !oldNode.EqualExceptExpire (node)) {
79+ ListNodesCache->Invalidate ();
80+ }
7681
7782 // If ID is re-used by another node then proxy has to be reset.
7883 if (exists && !oldNode.EqualExceptExpire (node))
@@ -202,31 +207,40 @@ void TDynamicNameserver::ResolveDynamicNode(ui32 nodeId,
202207 reply->NodeId = nodeId;
203208 ctx.Send (ev->Sender , reply);
204209 } else {
205- ctx.RegisterWithSameMailbox (new TDynamicNodeResolver (SelfId (), nodeId, DynamicConfigs[domain], ev, deadline));
210+ ctx.RegisterWithSameMailbox (new TDynamicNodeResolver (SelfId (), nodeId, DynamicConfigs[domain],
211+ ListNodesCache, ev, deadline));
206212 }
207213}
208214
209215void TDynamicNameserver::SendNodesList (const TActorContext &ctx)
210- {
216+ {
211217 auto now = ctx.Now ();
212- for (auto &sender : ListNodesQueue) {
213- THolder<TEvInterconnect::TEvNodesInfo> reply (new TEvInterconnect::TEvNodesInfo);
218+ if (ListNodesCache->NeedUpdate (now)) {
219+ auto newNodes = MakeIntrusive<TIntrusiveVector<TEvInterconnect::TNodeInfo>>();
220+ auto newExpire = now;
221+
214222 for (const auto &pr : StaticConfig->StaticNodeTable ) {
215- reply-> Nodes . emplace_back (pr.first ,
216- pr.second .Address , pr.second .Host , pr.second .ResolveHost ,
217- pr.second .Port , pr.second .Location , true );
223+ newNodes-> emplace_back (pr.first ,
224+ pr.second .Address , pr.second .Host , pr.second .ResolveHost ,
225+ pr.second .Port , pr.second .Location , true );
218226 }
219227
220228 for (auto &config : DynamicConfigs) {
221229 for (auto &pr : config->DynamicNodes ) {
222- if (pr.second .Expire > now)
223- reply->Nodes .emplace_back (pr.first , pr.second .Address ,
224- pr.second .Host , pr.second .ResolveHost ,
225- pr.second .Port , pr.second .Location , false );
230+ if (pr.second .Expire > now) {
231+ newNodes->emplace_back (pr.first , pr.second .Address ,
232+ pr.second .Host , pr.second .ResolveHost ,
233+ pr.second .Port , pr.second .Location , false );
234+ newExpire = std::min (newExpire, pr.second .Expire );
235+ }
226236 }
227237 }
228238
229- ctx.Send (sender, reply.Release ());
239+ ListNodesCache->Update (newNodes, newExpire);
240+ }
241+
242+ for (auto &sender : ListNodesQueue) {
243+ ctx.Send (sender, new TEvInterconnect::TEvNodesInfo (ListNodesCache->GetNodes ()));
230244 }
231245 ListNodesQueue.clear ();
232246}
@@ -282,15 +296,18 @@ void TDynamicNameserver::UpdateState(const NKikimrNodeBroker::TNodesInfo &rec,
282296 config->ExpiredNodes .emplace (node.GetNodeId (), info);
283297 }
284298
299+ ListNodesCache->Invalidate ();
285300 config->Epoch = rec.GetEpoch ();
286301 ctx.Schedule (config->Epoch .End - ctx.Now (),
287302 new TEvPrivate::TEvUpdateEpoch (domain, config->Epoch .Id + 1 ));
288303 } else {
289304 // Note: this update may be optimized to only include new nodes
290305 for (auto &node : rec.GetNodes ()) {
291306 auto nodeId = node.GetNodeId ();
292- if (!config->DynamicNodes .contains (nodeId))
307+ if (!config->DynamicNodes .contains (nodeId)) {
293308 config->DynamicNodes .emplace (nodeId, node);
309+ ListNodesCache->Invalidate ();
310+ }
294311 }
295312 config->Epoch = rec.GetEpoch ();
296313 }
@@ -377,8 +394,8 @@ void TDynamicNameserver::Handle(TEvInterconnect::TEvGetNode::TPtr &ev, const TAc
377394 ctx.Send (ev->Sender , reply.Release ());
378395 } else {
379396 const TInstant deadline = ev->Get ()->Deadline ;
380- ctx.RegisterWithSameMailbox (new TDynamicNodeSearcher (SelfId (), nodeId, DynamicConfigs[domain], ev. Release (),
381- deadline));
397+ ctx.RegisterWithSameMailbox (new TDynamicNodeSearcher (SelfId (), nodeId, DynamicConfigs[domain],
398+ ListNodesCache, ev. Release (), deadline));
382399 }
383400 }
384401}
@@ -437,6 +454,7 @@ void TDynamicNameserver::Handle(NConsole::TEvConsole::TEvConfigNotificationReque
437454 auto newStaticConfig = BuildNameserverTable (config.GetNameserviceConfig ());
438455 if (StaticConfig->StaticNodeTable != newStaticConfig->StaticNodeTable ) {
439456 StaticConfig = std::move (newStaticConfig);
457+ ListNodesCache->Invalidate ();
440458 for (const auto & subscriber : StaticNodeChangeSubscribers) {
441459 TActivationContext::Send (new IEventHandle (SelfId (), subscriber, new TEvInterconnect::TEvListNodes));
442460 }
@@ -478,5 +496,29 @@ TIntrusivePtr<TTableNameserverSetup> BuildNameserverTable(const NKikimrConfig::T
478496 return table;
479497}
480498
499+ TListNodesCache::TListNodesCache ()
500+ : Nodes(nullptr )
501+ , Expire(TInstant::Zero())
502+ {}
503+
504+
505+ void TListNodesCache::Update (TIntrusiveVector<TEvInterconnect::TNodeInfo>::TConstPtr newNodes, TInstant newExpire) {
506+ Nodes = newNodes;
507+ Expire = newExpire;
508+ }
509+
510+ void TListNodesCache::Invalidate () {
511+ Nodes = nullptr ;
512+ Expire = TInstant::Zero ();
513+ }
514+
515+ bool TListNodesCache::NeedUpdate (TInstant now) const {
516+ return Nodes == nullptr || now > Expire;
517+ }
518+
519+ TIntrusiveVector<TEvInterconnect::TNodeInfo>::TConstPtr TListNodesCache::GetNodes () const {
520+ return Nodes;
521+ }
522+
481523} // NNodeBroker
482524} // NKikimr
0 commit comments