@@ -93,26 +93,34 @@ void TViewerPipeClient::SendDelayedRequests() {
9393 }
9494}
9595
96- TPathId TViewerPipeClient::GetPathId (TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr & ev) {
97- if (ev-> Get ()-> Request ->ResultSet .size () == 1 ) {
98- if (ev-> Get ()-> Request ->ResultSet .begin ()->Self ) {
99- const auto & info = ev-> Get ()-> Request ->ResultSet .begin ()->Self ->Info ;
96+ TPathId TViewerPipeClient::GetPathId (const TEvTxProxySchemeCache::TEvNavigateKeySetResult& ev) {
97+ if (ev. Request ->ResultSet .size () == 1 ) {
98+ if (ev. Request ->ResultSet .begin ()->Self ) {
99+ const auto & info = ev. Request ->ResultSet .begin ()->Self ->Info ;
100100 return TPathId (info.GetSchemeshardId (), info.GetPathId ());
101101 }
102- if (ev-> Get ()-> Request ->ResultSet .begin ()->TableId ) {
103- return ev-> Get ()-> Request ->ResultSet .begin ()->TableId .PathId ;
102+ if (ev. Request ->ResultSet .begin ()->TableId ) {
103+ return ev. Request ->ResultSet .begin ()->TableId .PathId ;
104104 }
105105 }
106106 return {};
107107}
108108
109- TString TViewerPipeClient::GetPath (TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr & ev) {
110- if (ev-> Get ()-> Request ->ResultSet .size () == 1 ) {
111- return CanonizePath (ev-> Get ()-> Request ->ResultSet .begin ()->Path );
109+ TString TViewerPipeClient::GetPath (const TEvTxProxySchemeCache::TEvNavigateKeySetResult& ev) {
110+ if (ev. Request ->ResultSet .size () == 1 ) {
111+ return CanonizePath (ev. Request ->ResultSet .begin ()->Path );
112112 }
113113 return {};
114114}
115115
116+ TPathId TViewerPipeClient::GetPathId (TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev) {
117+ return GetPathId (*ev->Get ());
118+ }
119+
120+ TString TViewerPipeClient::GetPath (TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev) {
121+ return GetPath (*ev->Get ());
122+ }
123+
116124bool TViewerPipeClient::IsSuccess (const std::unique_ptr<TEvTxProxySchemeCache::TEvNavigateKeySetResult>& ev) {
117125 return (ev->Request ->ResultSet .size () == 1 ) && (ev->Request ->ResultSet .begin ()->Status == NSchemeCache::TSchemeCacheNavigate::EStatus::Ok);
118126}
@@ -147,6 +155,23 @@ TString TViewerPipeClient::GetError(const std::unique_ptr<TEvTxProxySchemeCache:
147155 }
148156}
149157
158+ bool TViewerPipeClient::IsSuccess (const std::unique_ptr<TEvStateStorage::TEvBoardInfo>& ev) {
159+ return ev->Status == TEvStateStorage::TEvBoardInfo::EStatus::Ok;
160+ }
161+
162+ TString TViewerPipeClient::GetError (const std::unique_ptr<TEvStateStorage::TEvBoardInfo>& ev) {
163+ switch (ev->Status ) {
164+ case TEvStateStorage::TEvBoardInfo::EStatus::Unknown:
165+ return " Unknown" ;
166+ case TEvStateStorage::TEvBoardInfo::EStatus::Ok:
167+ return " Ok" ;
168+ case TEvStateStorage::TEvBoardInfo::EStatus::NotAvailable:
169+ return " NotAvailable" ;
170+ default :
171+ return ::ToString (static_cast <int >(ev->Status ));
172+ }
173+ }
174+
150175void TViewerPipeClient::RequestHiveDomainStats (NNodeWhiteboard::TTabletId hiveId) {
151176 TActorId pipeClient = ConnectTabletPipe (hiveId);
152177 THolder<TEvHive::TEvRequestHiveDomainStats> request = MakeHolder<TEvHive::TEvRequestHiveDomainStats>();
@@ -540,10 +565,10 @@ void TViewerPipeClient::RequestStateStorageMetadataCacheEndpointsLookup(const TS
540565 ++Requests;
541566}
542567
543- std::vector<TNodeId> TViewerPipeClient::GetNodesFromBoardReply (TEvStateStorage::TEvBoardInfo::TPtr & ev) {
568+ std::vector<TNodeId> TViewerPipeClient::GetNodesFromBoardReply (const TEvStateStorage::TEvBoardInfo& ev) {
544569 std::vector<TNodeId> databaseNodes;
545- if (ev-> Get ()-> Status == TEvStateStorage::TEvBoardInfo::EStatus::Ok) {
546- for (const auto & [actorId, infoEntry] : ev-> Get ()-> InfoEntries ) {
570+ if (ev. Status == TEvStateStorage::TEvBoardInfo::EStatus::Ok) {
571+ for (const auto & [actorId, infoEntry] : ev. InfoEntries ) {
547572 databaseNodes.emplace_back (actorId.NodeId ());
548573 }
549574 }
@@ -552,11 +577,20 @@ std::vector<TNodeId> TViewerPipeClient::GetNodesFromBoardReply(TEvStateStorage::
552577 return databaseNodes;
553578}
554579
580+ std::vector<TNodeId> TViewerPipeClient::GetNodesFromBoardReply (TEvStateStorage::TEvBoardInfo::TPtr& ev) {
581+ return GetNodesFromBoardReply (*ev->Get ());
582+ }
583+
555584void TViewerPipeClient::InitConfig (const TCgiParameters& params) {
556585 Followers = FromStringWithDefault (params.Get (" followers" ), Followers);
557586 Metrics = FromStringWithDefault (params.Get (" metrics" ), Metrics);
558587 WithRetry = FromStringWithDefault (params.Get (" with_retry" ), WithRetry);
559588 MaxRequestsInFlight = FromStringWithDefault (params.Get (" max_requests_in_flight" ), MaxRequestsInFlight);
589+ Database = params.Get (" database" );
590+ if (!Database) {
591+ Database = params.Get (" tenant" );
592+ }
593+ Direct = FromStringWithDefault<bool >(params.Get (" direct" ), Direct);
560594}
561595
562596void TViewerPipeClient::InitConfig (const TRequestSettings& settings) {
@@ -653,23 +687,43 @@ void TViewerPipeClient::Handle(TEvTabletPipe::TEvClientConnected::TPtr& ev) {
653687 }
654688}
655689
690+ void TViewerPipeClient::HandleResolveResource (TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev) {
691+ ResourceNavigateResponse->Set (std::move (ev));
692+ if (ResourceNavigateResponse->IsOk ()) {
693+ TSchemeCacheNavigate::TEntry& entry (ResourceNavigateResponse->Get ()->Request ->ResultSet .front ());
694+ SharedDatabase = CanonizePath (entry.Path );
695+ if (SharedDatabase == AppData ()->TenantName ) {
696+ Direct = true ;
697+ return Bootstrap (); // retry bootstrap without redirect this time
698+ }
699+ DatabaseBoardInfoResponse = MakeRequestStateStorageEndpointsLookup (SharedDatabase);
700+ } else {
701+ ReplyAndPassAway (GetHTTPBADREQUEST (" text/plain" , " Failed to resolve database - shared database not found" ));
702+ }
703+ }
704+
656705void TViewerPipeClient::HandleResolveDatabase (TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev) {
657- if (ev->Get ()->Request ->ResultSet .size () == 1 && ev->Get ()->Request ->ResultSet .begin ()->Status == NSchemeCache::TSchemeCacheNavigate::EStatus::Ok) {
658- TSchemeCacheNavigate::TEntry& entry (ev->Get ()->Request ->ResultSet .front ());
659- if (entry.DomainInfo ) {
660- if (entry.DomainInfo ->ResourcesDomainKey && entry.DomainInfo ->DomainKey != entry.DomainInfo ->ResourcesDomainKey ) {
661- RequestSchemeCacheNavigate (TPathId (entry.DomainInfo ->ResourcesDomainKey ));
662- } else {
663- RequestStateStorageEndpointsLookup (CanonizePath (entry.Path ));
664- }
706+ DatabaseNavigateResponse->Set (std::move (ev));
707+ if (DatabaseNavigateResponse->IsOk ()) {
708+ TSchemeCacheNavigate::TEntry& entry (DatabaseNavigateResponse->Get ()->Request ->ResultSet .front ());
709+ if (entry.DomainInfo && entry.DomainInfo ->ResourcesDomainKey && entry.DomainInfo ->DomainKey != entry.DomainInfo ->ResourcesDomainKey ) {
710+ ResourceNavigateResponse = MakeRequestSchemeCacheNavigate (TPathId (entry.DomainInfo ->ResourcesDomainKey ));
711+ Become (&TViewerPipeClient::StateResolveResource);
712+ return ;
665713 }
714+ DatabaseBoardInfoResponse = MakeRequestStateStorageEndpointsLookup (CanonizePath (entry.Path ));
666715 } else {
667- ReplyAndPassAway (GetHTTPBADREQUEST (" text/plain" , " Failed to resolve database" ));
716+ ReplyAndPassAway (GetHTTPBADREQUEST (" text/plain" , " Failed to resolve database - not found " ));
668717 }
669718}
670719
671- void TViewerPipeClient::HandleResolveDatabase (TEvStateStorage::TEvBoardInfo::TPtr& ev) {
672- ReplyAndPassAway (MakeForward (GetNodesFromBoardReply (ev)));
720+ void TViewerPipeClient::HandleResolve (TEvStateStorage::TEvBoardInfo::TPtr& ev) {
721+ DatabaseBoardInfoResponse->Set (std::move (ev));
722+ if (DatabaseBoardInfoResponse->IsOk ()) {
723+ ReplyAndPassAway (MakeForward (GetNodesFromBoardReply (DatabaseBoardInfoResponse->GetRef ())));
724+ } else {
725+ ReplyAndPassAway (GetHTTPBADREQUEST (" text/plain" , " Failed to resolve database - no nodes found" ));
726+ }
673727}
674728
675729void TViewerPipeClient::HandleTimeout () {
@@ -678,15 +732,33 @@ void TViewerPipeClient::HandleTimeout() {
678732
679733STATEFN (TViewerPipeClient::StateResolveDatabase) {
680734 switch (ev->GetTypeRewrite ()) {
681- hFunc (TEvStateStorage::TEvBoardInfo, HandleResolveDatabase );
735+ hFunc (TEvStateStorage::TEvBoardInfo, HandleResolve );
682736 hFunc (TEvTxProxySchemeCache::TEvNavigateKeySetResult, HandleResolveDatabase);
683737 cFunc (TEvents::TEvWakeup::EventType, HandleTimeout);
684738 }
685739}
686740
741+ STATEFN (TViewerPipeClient::StateResolveResource) {
742+ switch (ev->GetTypeRewrite ()) {
743+ hFunc (TEvStateStorage::TEvBoardInfo, HandleResolve);
744+ hFunc (TEvTxProxySchemeCache::TEvNavigateKeySetResult, HandleResolveResource);
745+ cFunc (TEvents::TEvWakeup::EventType, HandleTimeout);
746+ }
747+ }
748+
687749void TViewerPipeClient::RedirectToDatabase (const TString& database) {
688- RequestSchemeCacheNavigate (database);
689- Become (&TViewerPipeClient::StateResolveDatabase, TDuration::MilliSeconds (1000 ), new TEvents::TEvWakeup ());
750+ DatabaseNavigateResponse = MakeRequestSchemeCacheNavigate (database);
751+ Become (&TViewerPipeClient::StateResolveDatabase);
752+ }
753+
754+ bool TViewerPipeClient::NeedToRedirect () {
755+ Direct |= !Event->Get ()->Request .GetHeader (" X-Forwarded-From-Node" ).empty (); // we're already forwarding
756+ Direct |= (Database == AppData ()->TenantName ) || Database.empty (); // we're already on the right node or don't use database filter
757+ if (Database && !Direct) {
758+ RedirectToDatabase (Database); // to find some dynamic node and redirect query there
759+ return true ;
760+ }
761+ return false ;
690762}
691763
692764void TViewerPipeClient::PassAway () {
0 commit comments