11#include " database_resolver.h"
22
3+ #include < util/string/split.h>
34#include < ydb/core/fq/libs/common/cache.h>
45#include < ydb/core/fq/libs/config/protos/issue_id.pb.h>
56#include < ydb/core/fq/libs/events/events.h>
@@ -98,8 +99,6 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
9899 }
99100
100101 void DieOnTtl () {
101- Success = false ;
102-
103102 auto errorMsg = TStringBuilder () << " Could not resolve database ids: " ;
104103 bool firstUnresolvedDbId = true ;
105104 for (const auto & [_, params]: Requests) {
@@ -112,46 +111,41 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
112111 }
113112 errorMsg << " in " << ResolvingTtl << " seconds." ;
114113 LOG_E (" ResponseProcessor::DieOnTtl: errorMsg=" << errorMsg);
115-
116- SendResolvedEndpointsAndDie (errorMsg );
114+ Issues. AddIssue (errorMsg);
115+ SendResolvedEndpointsAndDie ();
117116 }
118117
119- void SendResolvedEndpointsAndDie (const TString& errorMsg) {
120- NYql::TIssues issues;
121- if (errorMsg) {
122- issues.AddIssue (errorMsg);
123- }
124-
118+ void SendResolvedEndpointsAndDie () {
125119 Send (Sender,
126120 new TEvents::TEvEndpointResponse (
127- NYql::TDatabaseResolverResponse (std::move (DatabaseId2Description), Success, issues )));
121+ NYql::TDatabaseResolverResponse (std::move (DatabaseId2Description), Issues. Empty (), Issues )));
128122 PassAway ();
129123 LOG_D (" ResponseProcessor::SendResolvedEndpointsAndDie: passed away" );
130124 }
131125
132126 void Handle (NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr& ev)
133127 {
134- TString errorMessage;
135128 TMaybe<TDatabaseDescription> result;
136129 const auto requestIter = Requests.find (ev->Get ()->Request );
137130 HandledIds++;
138131
139- LOG_T (" ResponseProcessor::Handle(HttpIncomingResponse): got MDB API response: code=" << ev->Get ()->Response ->Status );
132+ LOG_T (" ResponseProcessor::Handle(HttpIncomingResponse): got API response: code=" << ev->Get ()->Response ->Status );
140133
141134 try {
142- HandleResponse (ev, requestIter, errorMessage, result);
135+ HandleResponse (ev, requestIter, result);
143136 } catch (...) {
144137 const TString msg = TStringBuilder () << " error while response processing, params "
145138 << ((requestIter != Requests.end ()) ? requestIter->second .ToDebugString () : TString{" unknown" })
146139 << " , details: " << CurrentExceptionMessage ();
147140 LOG_E (" ResponseProccessor::Handle(TEvHttpIncomingResponse): " << msg);
141+ Issues.AddIssue (msg);
148142 }
149143
150144 LOG_T (" ResponseProcessor::Handle(HttpIncomingResponse): progress: "
151145 << DatabaseId2Description.size () << " of " << Requests.size () << " requests are done" );
152146
153147 if (HandledIds == Requests.size ()) {
154- SendResolvedEndpointsAndDie (errorMessage );
148+ SendResolvedEndpointsAndDie ();
155149 }
156150 }
157151
@@ -160,18 +154,25 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
160154 void HandleResponse (
161155 NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr& ev,
162156 const TRequestMap::const_iterator& requestIter,
163- TString& errorMessage,
164157 TMaybe<TDatabaseDescription>& result)
165- {
166- if (ev->Get ()->Error .empty () && (ev->Get ()->Response && ev->Get ()->Response ->Status == " 200" )) {
167- errorMessage = HandleSuccessfulResponse (ev, requestIter, result);
158+ {
159+ TString errorMessage;
160+
161+ if (requestIter == Requests.end ()) {
162+ // Requests are guaranteed to be kept in within TResponseProcessor until the response arrives.
163+ // If there is no appropriate request, it's a fatal error.
164+ errorMessage = " Invariant violation: unknown request" ;
168165 } else {
169- errorMessage = HandleFailedResponse (ev, requestIter);
166+ if (ev->Get ()->Error .empty () && (ev->Get ()->Response && ev->Get ()->Response ->Status == " 200" )) {
167+ errorMessage = HandleSuccessfulResponse (ev, *requestIter, result);
168+ } else {
169+ errorMessage = HandleFailedResponse (ev, *requestIter);
170+ }
170171 }
171172
172173 if (errorMessage) {
174+ Issues.AddIssue (errorMessage);
173175 LOG_E (" ResponseProcessor::Handle(HttpIncomingResponse): error=" << errorMessage);
174- Success = false ;
175176 } else {
176177 const auto & params = requestIter->second ;
177178 auto key = std::make_tuple (params.Id , params.DatabaseType , params.DatabaseAuth );
@@ -191,17 +192,13 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
191192
192193 TString HandleSuccessfulResponse (
193194 NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr& ev,
194- const TRequestMap::const_iterator& requestIter ,
195+ const TRequestMap::value_type& requestWithParams ,
195196 TMaybe<TDatabaseDescription>& result
196197 ) {
197- if (requestIter == Requests.end ()) {
198- return " unknown request" ;
199- }
200-
201198 NJson::TJsonReaderConfig jsonConfig;
202199 NJson::TJsonValue databaseInfo;
203200
204- const auto & params = requestIter-> second ;
201+ const auto & params = requestWithParams. second ;
205202 const bool parseJsonOk = NJson::ReadJsonTree (ev->Get ()->Response ->Body , &jsonConfig, &databaseInfo);
206203 TParsers::const_iterator parserIt;
207204 if (parseJsonOk && (parserIt = Parsers.find (params.DatabaseType )) != Parsers.end ()) {
@@ -232,37 +229,37 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
232229
233230 TString HandleFailedResponse (
234231 NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr& ev,
235- const TRequestMap::const_iterator& requestIter
232+ const TRequestMap::value_type& requestWithParams
236233 ) const {
237- if (requestIter == Requests.end ()) {
238- return " unknown request" ;
239- }
234+ auto sb = TStringBuilder ()
235+ << " Error while trying to resolve managed " << ToString (requestWithParams.second .DatabaseType )
236+ << " database with id " << requestWithParams.second .Id << " via HTTP request to"
237+ << " : endpoint '" << requestWithParams.first ->Host << " '"
238+ << " , url '" << requestWithParams.first ->URL << " '"
239+ << " : " ;
240+
241+ // Handle network error (when the response is empty)
242+ if (!ev->Get ()->Response ) {
243+ return sb << ev->Get ()->Error ;
244+ }
240245
246+ // Handle unauthenticated error
241247 const auto & status = ev->Get ()->Response ->Status ;
242-
243248 if (status == " 403" ) {
244- return TStringBuilder () << " You have no permission to resolve database id into database endpoint. " + DetailedPermissionsError (requestIter-> second );
249+ return sb << " you have no permission to resolve database id into database endpoint." + DetailedPermissionsError (requestWithParams. second );
245250 }
246251
247- auto errorMessage = ev->Get ()->Error ;
248-
249- const TString error = TStringBuilder ()
250- << " Cannot resolve database id (status = " << status << " ). "
251- << " Response body from " << ev->Get ()->Request ->URL << " : " << (ev->Get ()->Response ? ev->Get ()->Response ->Body : " empty" );
252- if (!errorMessage.empty ()) {
253- errorMessage += ' \n ' ;
254- }
255- errorMessage += error;
256-
257- return errorMessage;
252+ // Unexpected error. Add response body for debug
253+ return sb << Endl
254+ << " Status: " << status << Endl
255+ << " Response body: " << ev->Get ()->Response ->Body ;
258256 }
259257
260258
261259 TString DetailedPermissionsError (const TResolveParams& params) const {
262-
263260 if (params.DatabaseType == EDatabaseType::ClickHouse || params.DatabaseType == EDatabaseType::PostgreSQL) {
264261 auto mdbTypeStr = NYql::DatabaseTypeLowercase (params.DatabaseType );
265- return TStringBuilder () << " Please check that your service account has role " <<
262+ return TStringBuilder () << " Please check that your service account has role " <<
266263 " `managed-" << mdbTypeStr << " .viewer`." ;
267264 }
268265 return {};
@@ -275,7 +272,7 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
275272 const NYql::IMdbEndpointGenerator::TPtr MdbEndpointGenerator;
276273 TDatabaseResolverResponse::TDatabaseDescriptionMap DatabaseId2Description;
277274 size_t HandledIds = 0 ;
278- bool Success = true ;
275+ NYql::TIssues Issues ;
279276 const TParsers& Parsers;
280277 TDuration ResolvingTtl = TDuration::Seconds(30 ); // TODO: Use cfg
281278};
@@ -312,7 +309,12 @@ class TDatabaseResolver: public TActor<TDatabaseResolver>
312309 }
313310
314311 Y_ENSURE (endpoint);
315- return TDatabaseDescription{endpoint, " " , 0 , database, secure};
312+
313+ TVector<TString> split = StringSplitter (endpoint).Split (' :' );
314+
315+ Y_ENSURE (split.size () == 2 );
316+
317+ return TDatabaseDescription{endpoint, split[0 ], FromString (split[1 ]), database, secure};
316318 };
317319 Parsers[NYql::EDatabaseType::Ydb] = ydbParser;
318320 Parsers[NYql::EDatabaseType::DataStreams] = [ydbParser](
@@ -327,9 +329,11 @@ class TDatabaseResolver: public TActor<TDatabaseResolver>
327329 if (!isDedicatedDb && ret.Endpoint .StartsWith (" ydb." )) {
328330 // Replace "ydb." -> "yds."
329331 ret.Endpoint [2 ] = ' s' ;
332+ ret.Host [2 ] = ' s' ;
330333 }
331334 if (isDedicatedDb) {
332335 ret.Endpoint = " u-" + ret.Endpoint ;
336+ ret.Host = " u-" + ret.Host ;
333337 }
334338 return ret;
335339 };
@@ -486,6 +490,7 @@ class TDatabaseResolver: public TActor<TDatabaseResolver>
486490 try {
487491 TString url;
488492 if (IsIn ({NYql::EDatabaseType::Ydb, NYql::EDatabaseType::DataStreams }, databaseType)) {
493+ YQL_ENSURE (ev->Get ()->YdbMvpEndpoint .Size () > 0 , " empty YDB MVP Endpoint" );
489494 url = TUrlBuilder (ev->Get ()->YdbMvpEndpoint + " /database" )
490495 .AddUrlParam (" databaseId" , databaseId)
491496 .Build ();
@@ -497,7 +502,6 @@ class TDatabaseResolver: public TActor<TDatabaseResolver>
497502 .AddPathComponent (" hosts" )
498503 .Build ();
499504 }
500- LOG_D (" ResponseProccessor::Handle(EndpointRequest): start GET request: " << url);
501505
502506 NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestGet (url);
503507
@@ -507,6 +511,8 @@ class TDatabaseResolver: public TActor<TDatabaseResolver>
507511 httpRequest->Set (" Authorization" , token);
508512 }
509513
514+ LOG_D (" ResponseProccessor::Handle(EndpointRequest): start GET request: " << " url: " << httpRequest->URL );
515+
510516 requests[httpRequest] = TResolveParams{databaseId, databaseType, databaseAuth};
511517 } catch (const std::exception& e) {
512518 const TString msg = TStringBuilder () << " error while preparing to resolve database id: " << databaseId
0 commit comments