1
1
#include " actors.h"
2
2
3
3
#include < ydb/core/base/path.h>
4
+ #include < ydb/core/base/tablet_pipe.h>
4
5
5
6
#include < ydb/core/kqp/common/simple/services.h>
6
7
#include < ydb/core/kqp/workload_service/common/events.h>
7
8
#include < ydb/core/kqp/workload_service/common/helpers.h>
8
9
10
+ #include < ydb/core/tx/schemeshard/schemeshard.h>
9
11
#include < ydb/core/tx/tx_proxy/proxy.h>
10
12
11
13
#include < ydb/library/table_creator/table_creator.h>
@@ -116,7 +118,7 @@ class TPoolResolverActor : public TActorBootstrapped<TPoolResolverActor> {
116
118
117
119
class TPoolFetcherActor : public TSchemeActorBase <TPoolFetcherActor> {
118
120
public:
119
- TPoolFetcherActor (const NActors:: TActorId& replyActorId, const TString& database, const TString& poolId, TIntrusiveConstPtr<NACLib::TUserToken> userToken, bool enableOnServerless)
121
+ TPoolFetcherActor (const TActorId& replyActorId, const TString& database, const TString& poolId, TIntrusiveConstPtr<NACLib::TUserToken> userToken, bool enableOnServerless)
120
122
: ReplyActorId(replyActorId)
121
123
, Database(database)
122
124
, PoolId(poolId)
@@ -255,38 +257,67 @@ class TPoolCreatorActor : public TSchemeActorBase<TPoolCreatorActor> {
255
257
}
256
258
257
259
void Handle (TEvTxUserProxy::TEvProposeTransactionStatus::TPtr& ev) {
258
- const auto ssStatus = ev->Get ()->Record .GetSchemeShardStatus ();
259
- switch (ev->Get ()->Status ()) {
260
+ const auto & response = ev->Get ()->Record ;
261
+ const auto ssStatus = response.GetSchemeShardStatus ();
262
+ const auto status = ev->Get ()->Status ();
263
+ switch (status) {
260
264
case NTxProxy::TResultStatus::ExecComplete:
261
265
case NTxProxy::TResultStatus::ExecAlready:
262
266
if (ssStatus == NKikimrScheme::EStatus::StatusSuccess || ssStatus == NKikimrScheme::EStatus::StatusAlreadyExists) {
263
267
Reply (Ydb::StatusIds::SUCCESS);
264
268
} else {
265
- Reply (Ydb::StatusIds::SCHEME_ERROR, TStringBuilder () << " Invalid creation status: " << static_cast <NKikimrScheme::EStatus>(ssStatus));
269
+ Reply (Ydb::StatusIds::SCHEME_ERROR, ExtractIssues (response, TStringBuilder () << " Invalid creation status: " << static_cast <NKikimrScheme::EStatus>(ssStatus) ));
266
270
}
267
271
return ;
268
272
case NTxProxy::TResultStatus::ExecError:
269
- if (ssStatus == NKikimrScheme::EStatus::StatusMultipleModifications || ssStatus == NKikimrScheme::EStatus::StatusInvalidParameter ) {
270
- ScheduleRetry (ssStatus, " Retry execution error " , true );
273
+ if (ssStatus == NKikimrScheme::EStatus::StatusMultipleModifications) {
274
+ SubscribeOnTransactionOrRetry (status, response );
271
275
} else {
272
- Reply (Ydb::StatusIds::SCHEME_ERROR, TStringBuilder () << " Execution error: " << static_cast <NKikimrScheme::EStatus>(ssStatus));
276
+ Reply (Ydb::StatusIds::SCHEME_ERROR, ExtractIssues (response, TStringBuilder () << " Execution error: " << static_cast <NKikimrScheme::EStatus>(ssStatus) ));
273
277
}
274
278
return ;
275
279
case NTxProxy::TResultStatus::ExecInProgress:
276
- ScheduleRetry (ssStatus, " Retry execution in progress error " , true );
280
+ SubscribeOnTransactionOrRetry (status, response );
277
281
return ;
278
282
case NTxProxy::TResultStatus::ProxyShardNotAvailable:
279
- ScheduleRetry (ssStatus , " Retry shard unavailable error" );
283
+ ScheduleRetry (response , " Retry shard unavailable error" );
280
284
return ;
281
285
default :
282
- Reply (Ydb::StatusIds::SCHEME_ERROR, TStringBuilder () << " Failed to create resource pool: " << static_cast <NKikimrScheme::EStatus>(ssStatus));
286
+ Reply (Ydb::StatusIds::SCHEME_ERROR, ExtractIssues (response, TStringBuilder () << " Failed to create resource pool: " << static_cast <NKikimrScheme::EStatus>(ssStatus) ));
283
287
return ;
284
288
}
285
289
}
286
290
291
+ void Handle (TEvTabletPipe::TEvClientConnected::TPtr& ev) {
292
+ if (ev->Get ()->Status == NKikimrProto::OK) {
293
+ LOG_T (" Tablet to pipe successfully connected" );
294
+ return ;
295
+ }
296
+
297
+ ClosePipeClient ();
298
+ ScheduleRetry (TStringBuilder () << " Tablet to pipe not connected: " << NKikimrProto::EReplyStatus_Name (ev->Get ()->Status ));
299
+ }
300
+
301
+ void Handle (TEvTabletPipe::TEvClientDestroyed::TPtr& ev) {
302
+ const TActorId clientId = ev->Get ()->ClientId ;
303
+ if (!ClosedSchemePipeActors.contains (clientId)) {
304
+ ClosePipeClient ();
305
+ ScheduleRetry (" Tablet to pipe destroyed" );
306
+ }
307
+ }
308
+
309
+ void Handle (NSchemeShard::TEvSchemeShard::TEvNotifyTxCompletionResult::TPtr& ev) {
310
+ ScheduleRetry (TStringBuilder () << " Transaction " << ev->Get ()->Record .GetTxId () << " completed, doublechecking" );
311
+ }
312
+
287
313
STFUNC (StateFunc) {
288
314
switch (ev->GetTypeRewrite ()) {
289
315
hFunc (TEvTxUserProxy::TEvProposeTransactionStatus, Handle )
316
+ hFunc (TEvTabletPipe::TEvClientConnected, Handle )
317
+ hFunc (TEvTabletPipe::TEvClientDestroyed, Handle )
318
+ hFunc (NSchemeShard::TEvSchemeShard::TEvNotifyTxCompletionResult, Handle )
319
+ IgnoreFunc (NSchemeShard::TEvSchemeShard::TEvNotifyTxCompletionRegistered)
320
+
290
321
default :
291
322
StateFuncBase (ev);
292
323
}
@@ -301,13 +332,12 @@ class TPoolCreatorActor : public TSchemeActorBase<TPoolCreatorActor> {
301
332
schemeTx.SetWorkingDir (JoinPath ({Database, " .resource_pools" }));
302
333
schemeTx.SetOperationType (NKikimrSchemeOp::ESchemeOpCreateResourcePool);
303
334
schemeTx.SetInternal (true );
304
- schemeTx.SetAllowAccessToPrivatePaths (true );
305
335
306
336
BuildCreatePoolRequest (*schemeTx.MutableCreateResourcePool ());
307
337
BuildModifyAclRequest (*schemeTx.MutableModifyACL ());
308
338
309
339
if (UserToken) {
310
- event->Record .SetUserToken (UserToken->GetSerializedToken ());
340
+ event->Record .SetUserToken (UserToken->SerializeAsString ());
311
341
}
312
342
313
343
Send (MakeTxProxyID (), std::move (event));
@@ -322,10 +352,42 @@ class TPoolCreatorActor : public TSchemeActorBase<TPoolCreatorActor> {
322
352
}
323
353
324
354
private:
325
- void ScheduleRetry (ui32 status, const TString& message, bool longDelay = false ) {
326
- auto ssStatus = static_cast <NKikimrScheme::EStatus>(status);
327
- if (!TBase::ScheduleRetry (TStringBuilder () << message << " , status: " << ssStatus, longDelay)) {
328
- Reply (Ydb::StatusIds::UNAVAILABLE, TStringBuilder () << " Retry limit exceeded on status: " << ssStatus);
355
+ void SubscribeOnTransactionOrRetry (NTxProxy::TResultStatus::EStatus status, const NKikimrTxUserProxy::TEvProposeTransactionStatus& response) {
356
+ const ui64 txId = status == NTxProxy::TResultStatus::ExecInProgress ? response.GetTxId () : response.GetPathCreateTxId ();
357
+ if (txId == 0 ) {
358
+ ScheduleRetry (response, " Unable to subscribe to concurrent transaction" , true );
359
+ return ;
360
+ }
361
+
362
+ SchemePipeActorId = Register (NTabletPipe::CreateClient (SelfId (), response.GetSchemeShardTabletId ()));
363
+
364
+ auto request = MakeHolder<NSchemeShard::TEvSchemeShard::TEvNotifyTxCompletion>();
365
+ request->Record .SetTxId (txId);
366
+ NTabletPipe::SendData (SelfId (), SchemePipeActorId, std::move (request));
367
+ LOG_D (" Subscribe on create pool tx: " << txId);
368
+ }
369
+
370
+ void ClosePipeClient () {
371
+ if (SchemePipeActorId) {
372
+ ClosedSchemePipeActors.insert (SchemePipeActorId);
373
+ NTabletPipe::CloseClient (SelfId (), SchemePipeActorId);
374
+ SchemePipeActorId = {};
375
+ }
376
+ }
377
+
378
+ void ScheduleRetry (const NKikimrTxUserProxy::TEvProposeTransactionStatus& response, const TString& message, bool longDelay = false ) {
379
+ ClosePipeClient ();
380
+
381
+ auto ssStatus = static_cast <NKikimrScheme::EStatus>(response.GetSchemeShardStatus ());
382
+ if (!TBase::ScheduleRetry (ExtractIssues (response, TStringBuilder () << message << " , status: " << ssStatus), longDelay)) {
383
+ Reply (Ydb::StatusIds::UNAVAILABLE, ExtractIssues (response, TStringBuilder () << " Retry limit exceeded on status: " << ssStatus));
384
+ }
385
+ }
386
+
387
+ void ScheduleRetry (const TString& message, bool longDelay = false ) {
388
+ ClosePipeClient ();
389
+ if (!TBase::ScheduleRetry (message, longDelay)) {
390
+ Reply (Ydb::StatusIds::UNAVAILABLE, TStringBuilder () << " Retry limit exceeded on error: " << message);
329
391
}
330
392
}
331
393
@@ -358,18 +420,29 @@ class TPoolCreatorActor : public TSchemeActorBase<TPoolCreatorActor> {
358
420
LOG_W (" Failed to create pool, " << status << " , issues: " << issues.ToOneLineString ());
359
421
}
360
422
423
+ ClosePipeClient ();
424
+
361
425
Issues.AddIssues (std::move (issues));
362
426
Send (ReplyActorId, new TEvPrivate::TEvCreatePoolResponse (status, std::move (Issues)));
363
427
PassAway ();
364
428
}
365
429
430
+ static NYql::TIssues ExtractIssues (const NKikimrTxUserProxy::TEvProposeTransactionStatus& response, const TString& message) {
431
+ NYql::TIssues issues;
432
+ NYql::IssuesFromMessage (response.GetIssues (), issues);
433
+ return GroupIssues (issues, message);
434
+ }
435
+
366
436
private:
367
437
const TActorId ReplyActorId;
368
438
const TString Database;
369
439
const TString PoolId;
370
440
const TIntrusiveConstPtr<NACLib::TUserToken> UserToken;
371
441
const NACLibProto::TDiffACL DiffAcl;
372
442
NResourcePool::TPoolSettings PoolConfig;
443
+
444
+ std::unordered_set<TActorId> ClosedSchemePipeActors;
445
+ TActorId SchemePipeActorId;
373
446
};
374
447
375
448
} // anonymous namespace
0 commit comments