Skip to content

Commit ad77dc0

Browse files
committed
improve redirects and tabletinfo filtering for serverless databases (#13888)
1 parent c07d0ff commit ad77dc0

File tree

6 files changed

+72
-27
lines changed

6 files changed

+72
-27
lines changed

ydb/core/protos/node_whiteboard.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ message TEvTabletStateRequest {
7474
optional string Format = 5; // it could be "packed5"
7575
optional string GroupBy = 20; // it's either empty or "Type,State" for now
7676
repeated fixed64 FilterTabletId = 22;
77+
optional NKikimrSubDomains.TDomainKey FilterTenantId = 23;
7778
}
7879

7980
message TEvTabletStateResponse {

ydb/core/tablet/node_whiteboard.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -808,24 +808,32 @@ class TNodeWhiteboardService : public TActorBootstrapped<TNodeWhiteboardService>
808808
void Handle(TEvWhiteboard::TEvTabletStateRequest::TPtr &ev, const TActorContext &ctx) {
809809
auto now = TMonotonic::Now();
810810
const auto& request = ev->Get()->Record;
811+
auto matchesFilter = [
812+
changedSince = request.has_changedsince() ? request.changedsince() : 0,
813+
filterTenantId = request.has_filtertenantid() ? NKikimr::TSubDomainKey(request.filtertenantid()) : NKikimr::TSubDomainKey()
814+
](const NKikimrWhiteboard::TTabletStateInfo& tabletStateInfo) {
815+
return tabletStateInfo.changetime() >= changedSince
816+
&& (!filterTenantId || filterTenantId == NKikimr::TSubDomainKey(tabletStateInfo.tenantid()));
817+
};
811818
std::unique_ptr<TEvWhiteboard::TEvTabletStateResponse> response = std::make_unique<TEvWhiteboard::TEvTabletStateResponse>();
812819
auto& record = response->Record;
813820
if (request.format() == "packed5") {
814821
TEvWhiteboard::TEvTabletStateResponsePacked5* ptr = response->AllocatePackedResponse(TabletStateInfo.size());
815822
for (const auto& [tabletId, tabletInfo] : TabletStateInfo) {
816-
ptr->TabletId = tabletInfo.tabletid();
817-
ptr->FollowerId = tabletInfo.followerid();
818-
ptr->Generation = tabletInfo.generation();
819-
ptr->Type = tabletInfo.type();
820-
ptr->State = tabletInfo.state();
821-
++ptr;
823+
if (matchesFilter(tabletInfo)) {
824+
ptr->TabletId = tabletInfo.tabletid();
825+
ptr->FollowerId = tabletInfo.followerid();
826+
ptr->Generation = tabletInfo.generation();
827+
ptr->Type = tabletInfo.type();
828+
ptr->State = tabletInfo.state();
829+
++ptr;
830+
}
822831
}
823832
} else {
824833
if (request.groupby().empty()) {
825-
ui64 changedSince = request.has_changedsince() ? request.changedsince() : 0;
826834
if (request.filtertabletid_size() == 0) {
827835
for (const auto& pr : TabletStateInfo) {
828-
if (pr.second.changetime() >= changedSince) {
836+
if (matchesFilter(pr.second)) {
829837
NKikimrWhiteboard::TTabletStateInfo& tabletStateInfo = *record.add_tabletstateinfo();
830838
Copy(tabletStateInfo, pr.second, request);
831839
}
@@ -834,7 +842,7 @@ class TNodeWhiteboardService : public TActorBootstrapped<TNodeWhiteboardService>
834842
for (auto tabletId : request.filtertabletid()) {
835843
auto it = TabletStateInfo.find({tabletId, 0});
836844
if (it != TabletStateInfo.end()) {
837-
if (it->second.changetime() >= changedSince) {
845+
if (matchesFilter(it->second)) {
838846
NKikimrWhiteboard::TTabletStateInfo& tabletStateInfo = *record.add_tabletstateinfo();
839847
Copy(tabletStateInfo, it->second, request);
840848
}
@@ -845,6 +853,9 @@ class TNodeWhiteboardService : public TActorBootstrapped<TNodeWhiteboardService>
845853
std::unordered_map<std::pair<NKikimrTabletBase::TTabletTypes::EType,
846854
NKikimrWhiteboard::TTabletStateInfo::ETabletState>, NKikimrWhiteboard::TTabletStateInfo> stateGroupBy;
847855
for (const auto& [id, stateInfo] : TabletStateInfo) {
856+
if (!matchesFilter(stateInfo)) {
857+
continue;
858+
}
848859
NKikimrWhiteboard::TTabletStateInfo& state = stateGroupBy[{stateInfo.type(), stateInfo.state()}];
849860
auto count = state.count();
850861
if (count == 0) {

ydb/core/viewer/json_pipe_req.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -776,13 +776,9 @@ void TViewerPipeClient::HandleResolveResource(TEvTxProxySchemeCache::TEvNavigate
776776
if (ResourceNavigateResponse->IsOk()) {
777777
TSchemeCacheNavigate::TEntry& entry(ResourceNavigateResponse->Get()->Request->ResultSet.front());
778778
SharedDatabase = CanonizePath(entry.Path);
779-
if (SharedDatabase == AppData()->TenantName) {
780-
Direct = true;
781-
Bootstrap(); // retry bootstrap without redirect this time
782-
} else {
783-
DatabaseBoardInfoResponse = MakeRequestStateStorageEndpointsLookup(SharedDatabase);
784-
--Requests; // don't count this request
785-
}
779+
Direct |= (SharedDatabase == AppData()->TenantName);
780+
DatabaseBoardInfoResponse = MakeRequestStateStorageEndpointsLookup(SharedDatabase);
781+
--Requests; // don't count this request
786782
} else {
787783
AddEvent("Failed to resolve database - shared database not found");
788784
Direct = true;
@@ -801,7 +797,8 @@ void TViewerPipeClient::HandleResolveDatabase(TEvTxProxySchemeCache::TEvNavigate
801797
--Requests; // don't count this request
802798
Become(&TViewerPipeClient::StateResolveResource);
803799
} else {
804-
DatabaseBoardInfoResponse = MakeRequestStateStorageEndpointsLookup(CanonizePath(entry.Path));
800+
Database = CanonizePath(entry.Path);
801+
DatabaseBoardInfoResponse = MakeRequestStateStorageEndpointsLookup(Database);
805802
--Requests; // don't count this request
806803
}
807804
} else {
@@ -816,7 +813,11 @@ void TViewerPipeClient::HandleResolve(TEvStateStorage::TEvBoardInfo::TPtr& ev) {
816813
if (DatabaseBoardInfoResponse) {
817814
DatabaseBoardInfoResponse->Set(std::move(ev));
818815
if (DatabaseBoardInfoResponse->IsOk()) {
819-
return ReplyAndPassAway(MakeForward(GetNodesFromBoardReply(DatabaseBoardInfoResponse->GetRef())));
816+
if (Direct) {
817+
Bootstrap(); // retry bootstrap without redirect this time
818+
} else {
819+
ReplyAndPassAway(MakeForward(GetNodesFromBoardReply(DatabaseBoardInfoResponse->GetRef())));
820+
}
820821
} else {
821822
AddEvent("Failed to resolve database nodes");
822823
Direct = true;
@@ -852,10 +853,11 @@ void TViewerPipeClient::RedirectToDatabase(const TString& database) {
852853
}
853854

854855
bool TViewerPipeClient::NeedToRedirect() {
855-
if (Event) {
856+
if (NeedRedirect && Event) {
857+
NeedRedirect = false;
856858
Direct |= !Event->Get()->Request.GetHeader("X-Forwarded-From-Node").empty(); // we're already forwarding
857859
Direct |= (Database == AppData()->TenantName) || Database.empty(); // we're already on the right node or don't use database filter
858-
if (Database && !Direct) {
860+
if (Database) {
859861
RedirectToDatabase(Database); // to find some dynamic node and redirect query there
860862
return true;
861863
}

ydb/core/viewer/json_pipe_req.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class TViewerPipeClient : public TActorBootstrapped<TViewerPipeClient> {
4242
TString Database;
4343
TString SharedDatabase;
4444
bool Direct = false;
45+
bool NeedRedirect = true;
4546
ui32 Requests = 0;
4647
bool PassedAway = false;
4748
ui32 MaxRequestsInFlight = 200;

ydb/core/viewer/viewer_tabletinfo.h

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ class TJsonTabletInfo : public TJsonWhiteboardRequest<TEvWhiteboard::TEvTabletSt
7474
std::unordered_map<ui64, TString> EndOfRangeKeyPrefix;
7575
TTabletId HiveId;
7676
bool IsBase64Encode = true;
77+
NKikimr::TSubDomainKey FilterTenantId;
78+
7779
public:
7880
TJsonTabletInfo(IViewer *viewer, NMon::TEvHttpInfo::TPtr &ev)
7981
: TJsonWhiteboardRequest(viewer, ev)
@@ -88,11 +90,25 @@ class TJsonTabletInfo : public TJsonWhiteboardRequest<TEvWhiteboard::TEvTabletSt
8890
}
8991
const auto& params(Event->Get()->Request.GetParams());
9092
TBase::RequestSettings.Timeout = FromStringWithDefault<ui32>(params.Get("timeout"), 10000);
91-
93+
if (DatabaseNavigateResponse && DatabaseNavigateResponse->IsOk()) {
94+
TPathId domainRoot;
95+
if (AppData()) {
96+
TIntrusivePtr<TDomainsInfo> domains = AppData()->DomainsInfo;
97+
auto* domain = domains->GetDomain();
98+
if (domain) {
99+
domainRoot = TPathId(domain->SchemeRoot, 1);
100+
}
101+
}
102+
if (DatabaseNavigateResponse->Get()->Request->ResultSet.front().DomainInfo->DomainKey != domainRoot) {
103+
const TPathId& pathId(DatabaseNavigateResponse->Get()->Request->ResultSet.front().DomainInfo->DomainKey);
104+
FilterTenantId.first = pathId.OwnerId;
105+
FilterTenantId.second = pathId.LocalPathId;
106+
}
107+
}
92108
if (DatabaseBoardInfoResponse && DatabaseBoardInfoResponse->IsOk()) {
93109
TBase::RequestSettings.FilterNodeIds = TBase::GetNodesFromBoardReply(DatabaseBoardInfoResponse->GetRef());
94-
} else if (Database) {
95-
RequestStateStorageEndpointsLookup(Database);
110+
} else if (Database || SharedDatabase) {
111+
RequestStateStorageEndpointsLookup(SharedDatabase ? SharedDatabase : Database);
96112
Become(&TThis::StateRequestedLookup, TDuration::MilliSeconds(TBase::RequestSettings.Timeout), new TEvents::TEvWakeup());
97113
return;
98114
}
@@ -125,6 +141,10 @@ class TJsonTabletInfo : public TJsonWhiteboardRequest<TEvWhiteboard::TEvTabletSt
125141
}
126142
}
127143
}
144+
if (FilterTenantId) {
145+
request->Record.MutableFilterTenantId()->SetSchemeShard(FilterTenantId.GetSchemeShard());
146+
request->Record.MutableFilterTenantId()->SetPathId(FilterTenantId.GetPathId());
147+
}
128148
return request;
129149
}
130150

@@ -368,8 +388,14 @@ class TJsonTabletInfo : public TJsonWhiteboardRequest<TEvWhiteboard::TEvTabletSt
368388
result.SetResponseTime(response.GetResponseTime());
369389
response = std::move(result);
370390
}
371-
for (NKikimrWhiteboard::TTabletStateInfo& info : *response.MutableTabletStateInfo()) {
372-
info.SetOverall(GetWhiteboardFlag(GetFlagFromTabletState(info.GetState())));
391+
auto& cont(*response.MutableTabletStateInfo());
392+
for (auto it = cont.begin(); it != cont.end();) {
393+
if (FilterTenantId && NKikimr::TSubDomainKey(it->GetTenantId()) != FilterTenantId) {
394+
it = cont.erase(it);
395+
} else {
396+
it->SetOverall(GetWhiteboardFlag(GetFlagFromTabletState(it->GetState())));
397+
++it;
398+
}
373399
}
374400
TBase::FilterResponse(response);
375401
}

ydb/core/viewer/viewer_tenantinfo.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,11 @@ class TJsonTenantInfo : public TViewerPipeClient {
124124
if (Database.empty()) {
125125
ListTenantsResponse = MakeRequestConsoleListTenants();
126126
} else {
127-
NavigateKeySetResult[Database] = MakeRequestSchemeCacheNavigate(Database);
128127
if (Database != DomainPath) {
128+
NavigateKeySetResult[Database] = MakeRequestSchemeCacheNavigate(Database);
129129
TenantStatusResponses[Database] = MakeRequestConsoleGetTenantStatus(Database);
130+
} else if (DatabaseNavigateResponse && DatabaseNavigateResponse->IsOk()) {
131+
NavigateKeySetResult[Database] = std::move(DatabaseNavigateResponse.value());
130132
}
131133
}
132134

@@ -137,7 +139,9 @@ class TJsonTenantInfo : public TViewerPipeClient {
137139
tenant.SetType(NKikimrViewer::Domain);
138140
tenant.SetName(DomainPath);
139141
RequestMetadataCacheHealthCheck(DomainPath);
140-
NavigateKeySetResult[DomainPath] = MakeRequestSchemeCacheNavigate(DomainPath);
142+
if (Database.empty() || !DatabaseNavigateResponse || !DatabaseNavigateResponse->IsOk()) {
143+
NavigateKeySetResult[DomainPath] = MakeRequestSchemeCacheNavigate(DomainPath);
144+
}
141145
}
142146

143147
HiveDomainStats[RootHiveId] = MakeRequestHiveDomainStats(RootHiveId);

0 commit comments

Comments
 (0)