@@ -40,6 +40,7 @@ struct RequestedKeyColumn {
40
40
struct TShardReadState {
41
41
std::vector<TOwnedCellVec> Keys;
42
42
ui32 FirstUnprocessedQuery = 0 ;
43
+ Ydb::StatusIds::StatusCode Status = Ydb::StatusIds::STATUS_CODE_UNSPECIFIED;
43
44
};
44
45
45
46
}
@@ -338,6 +339,14 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
338
339
Become (&TThis::MainState);
339
340
340
341
LOG_DEBUG_S (TlsActivationContext->AsActorContext (), NKikimrServices::RPC_REQUEST, " TReadRowsRPC bootstraped " );
342
+
343
+ auto selfId = ctx.SelfID ;
344
+ auto * actorSystem = ctx.ActorSystem ();
345
+ auto clientLostCb = [selfId, actorSystem]() {
346
+ actorSystem->Send (selfId, new TRpcServices::TEvForgetOperation ());
347
+ };
348
+
349
+ Request->SetFinishAction (std::move (clientLostCb));
341
350
}
342
351
343
352
bool ResolveTable () {
@@ -454,7 +463,7 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
454
463
}
455
464
}
456
465
457
- void Handle (TEvTxProxySchemeCache::TEvResolveKeySetResult::TPtr & ev) {
466
+ void Handle (TEvTxProxySchemeCache::TEvResolveKeySetResult::TPtr& ev) {
458
467
TEvTxProxySchemeCache::TEvResolveKeySetResult *msg = ev->Get ();
459
468
auto & resolvePartitionsResult = msg->Request ;
460
469
@@ -519,8 +528,7 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
519
528
if (it == ShardIdToReadState.end ()) {
520
529
TStringStream ss;
521
530
ss << " Got unknown shardId from TEvReadResult# " << shardId << " , status# " << statusCode;
522
- ReplyWithError (statusCode, ss.Str (), &issues);
523
- return ;
531
+ return ReplyWithError (statusCode, ss.Str (), &issues);
524
532
}
525
533
526
534
switch (statusCode) {
@@ -531,6 +539,7 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
531
539
if (Retries < MaxTotalRetries) {
532
540
TStringStream ss;
533
541
ss << " Reached MaxRetries count for DataShard# " << shardId << " , status# " << statusCode;
542
+ it->second .Status = statusCode;
534
543
ReplyWithError (statusCode, ss.Str (), &issues);
535
544
} else {
536
545
SendRead (shardId, it->second );
@@ -545,8 +554,8 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
545
554
if (statusCode != Ydb::StatusIds::OVERLOADED) {
546
555
statusCode = Ydb::StatusIds::ABORTED;
547
556
}
548
- ReplyWithError (statusCode, ss. Str (), &issues) ;
549
- return ;
557
+ it-> second . Status = statusCode ;
558
+ return ReplyWithError (statusCode, ss. Str (), &issues) ;
550
559
}
551
560
}
552
561
if (!msg->Record .HasFinished () || !msg->Record .GetFinished ()) {
@@ -562,6 +571,9 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
562
571
// we just wait for the next batch of results.
563
572
it->second .FirstUnprocessedQuery = token.GetFirstUnprocessedQuery ();
564
573
ReadsInFlight++;
574
+ } else {
575
+ // Read for this shard has finished
576
+ it->second .Status = statusCode;
565
577
}
566
578
}
567
579
LOG_DEBUG_S (TlsActivationContext->AsActorContext (), NKikimrServices::RPC_REQUEST, " TReadRowsRPC TEvReadResult RowsCount: " << msg->GetRowsCount ());
@@ -720,14 +732,48 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
720
732
PassAway ();
721
733
}
722
734
735
+ void CancelReads () {
736
+ TStringStream ss;
737
+ ss << " TReadRowsRPC CancelReads, shardIds# [" ;
738
+
739
+ bool hasActiveReads = false ;
740
+
741
+ for (const auto & [shardId, state] : ShardIdToReadState) {
742
+ if (state.Status != Ydb::StatusIds::STATUS_CODE_UNSPECIFIED) {
743
+ // Read has already finished for this shard
744
+ continue ;
745
+ }
746
+ auto request = std::make_unique<TEvDataShard::TEvReadCancel>();
747
+ auto & record = request->Record ;
748
+ record.SetReadId (shardId); // shardId is also a readId
749
+ Send (PipeCache, new TEvPipeCache::TEvForward (request.release (), shardId, true ), IEventHandle::FlagTrackDelivery, 0 , Span.GetTraceId ());
750
+ ss << shardId << " , " ;
751
+ hasActiveReads = true ;
752
+ }
753
+
754
+ ss << " ]" ;
755
+
756
+ if (hasActiveReads) {
757
+ LOG_WARN_S (TlsActivationContext->AsActorContext (), NKikimrServices::RPC_REQUEST, ss.Str ());
758
+ }
759
+ }
760
+
723
761
void HandleTimeout (TEvents::TEvWakeup::TPtr&) {
724
- return ReplyWithError (Ydb::StatusIds::TIMEOUT, TStringBuilder () << " ReadRows from table " << GetTable ()
762
+ ReplyWithError (Ydb::StatusIds::TIMEOUT, TStringBuilder () << " ReadRows from table " << GetTable ()
725
763
<< " timed out, duration: " << (TAppData::TimeProvider->Now () - StartTime).Seconds () << " sec" );
726
764
}
727
765
766
+ void HandleForget (TRpcServices::TEvForgetOperation::TPtr& ev) {
767
+ Y_UNUSED (ev);
768
+
769
+ ReplyWithError (Ydb::StatusIds::CANCELLED, TStringBuilder () << " ReadRows from table " << GetTable ()
770
+ << " cancelled, because client disconnected" );
771
+ }
772
+
728
773
void ReplyWithError (const Ydb::StatusIds::StatusCode& status, const TString& errorMsg,
729
774
const ::google::protobuf::RepeatedPtrField<Ydb::Issue::IssueMessage>* issues = nullptr )
730
775
{
776
+ CancelReads ();
731
777
LOG_ERROR_S (TlsActivationContext->AsActorContext (), NKikimrServices::RPC_REQUEST, " TReadRowsRPC ReplyWithError: " << errorMsg);
732
778
SendResult (status, errorMsg, issues);
733
779
}
@@ -736,7 +782,7 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
736
782
return ReplyWithError (Ydb::StatusIds::INTERNAL_ERROR, " Internal error: pipe cache is not available, the cluster might not be configured properly" );
737
783
}
738
784
739
- void Handle (TEvPipeCache::TEvDeliveryProblem::TPtr & ev) {
785
+ void Handle (TEvPipeCache::TEvDeliveryProblem::TPtr& ev) {
740
786
return ReplyWithError (Ydb::StatusIds::UNAVAILABLE, TStringBuilder () << " Failed to connect to shard " << ev->Get ()->TabletId );
741
787
}
742
788
@@ -760,6 +806,7 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
760
806
hFunc (TEvPipeCache::TEvDeliveryProblem, Handle);
761
807
762
808
hFunc (TEvents::TEvWakeup, HandleTimeout);
809
+ hFunc (TRpcServices::TEvForgetOperation, HandleForget);
763
810
}
764
811
}
765
812
0 commit comments