@@ -37,6 +37,11 @@ struct RequestedKeyColumn {
37
37
Ydb::Type Type;
38
38
};
39
39
40
+ struct TShardReadState {
41
+ std::vector<TOwnedCellVec> Keys;
42
+ ui32 FirstUnprocessedQuery = 0 ;
43
+ };
44
+
40
45
}
41
46
42
47
namespace {
@@ -445,7 +450,7 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
445
450
return (cmp < 0 );
446
451
});
447
452
Y_ABORT_UNLESS (it != partitions.end ());
448
- ShardIdToKeys [it->ShardId ].emplace_back (std::move (key));
453
+ ShardIdToReadState [it->ShardId ]. Keys .emplace_back (std::move (key));
449
454
}
450
455
}
451
456
@@ -462,12 +467,13 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
462
467
auto keyRange = resolvePartitionsResult->ResultSet [0 ].KeyDescription .Get ();
463
468
464
469
CreateShardToKeysMapping (keyRange);
465
- for (const auto & [shardId, keys ] : ShardIdToKeys ) {
466
- SendRead (shardId, keys );
470
+ for (const auto & [shardId, state ] : ShardIdToReadState ) {
471
+ SendRead (shardId, state );
467
472
}
468
473
}
469
474
470
- void SendRead (ui64 shardId, const std::vector<TOwnedCellVec>& keys) {
475
+ void SendRead (ui64 shardId, const TShardReadState& readState) {
476
+ auto & keys = readState.Keys ;
471
477
auto request = std::make_unique<TEvDataShard::TEvRead>();
472
478
auto & record = request->Record ;
473
479
@@ -482,8 +488,8 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
482
488
483
489
record.SetResultFormat (::NKikimrDataEvents::FORMAT_CELLVEC);
484
490
485
- for (auto & key : keys) {
486
- request->Keys .emplace_back (TSerializedCellVec::Serialize (key ));
491
+ for (size_t i = readState. FirstUnprocessedQuery ; i < keys. size (); ++i ) {
492
+ request->Keys .emplace_back (TSerializedCellVec::Serialize (keys[i] ));
487
493
}
488
494
489
495
LOG_DEBUG_S (TlsActivationContext->AsActorContext (), NKikimrServices::RPC_REQUEST, " TReadRowsRPC send TEvRead shardId : " << shardId << " keys.size(): " << keys.size ());
@@ -500,7 +506,7 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
500
506
// ReadRows can reply with the following statuses:
501
507
// * SUCCESS
502
508
// * INTERNAL_ERROR -- only if MaxRetries is reached
503
- // * OVERLOADED -- client will retrie it with backoff
509
+ // * OVERLOADED -- client will retry it with backoff
504
510
// * ABORTED -- code is used for all other DataShard errors
505
511
506
512
const auto & status = msg->Record .GetStatus ();
@@ -509,17 +515,20 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
509
515
510
516
ui64 shardId = msg->Record .GetReadId ();
511
517
518
+ auto it = ShardIdToReadState.find (shardId);
519
+ if (it == ShardIdToReadState.end ()) {
520
+ TStringStream ss;
521
+ ss << " Got unknown shardId from TEvReadResult# " << shardId << " , status# " << statusCode;
522
+ ReplyWithError (statusCode, ss.Str (), &issues);
523
+ return ;
524
+ }
525
+
512
526
switch (statusCode) {
513
527
case Ydb::StatusIds::SUCCESS:
514
528
break ;
515
529
case Ydb::StatusIds::INTERNAL_ERROR: {
516
- auto it = ShardIdToKeys.find (shardId);
517
530
++Retries;
518
- if (it == ShardIdToKeys.end ()) {
519
- TStringStream ss;
520
- ss << " Got unknown shardId from TEvReadResult# " << shardId << " , status# " << statusCode;
521
- ReplyWithError (statusCode, ss.Str (), &issues);
522
- } else if (Retries < MaxTotalRetries) {
531
+ if (Retries < MaxTotalRetries) {
523
532
TStringStream ss;
524
533
ss << " Reached MaxRetries count for DataShard# " << shardId << " , status# " << statusCode;
525
534
ReplyWithError (statusCode, ss.Str (), &issues);
@@ -540,8 +549,21 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
540
549
return ;
541
550
}
542
551
}
552
+ if (!msg->Record .HasFinished () || !msg->Record .GetFinished ()) {
553
+ // We should have received continuation token if read is not finished.
554
+ TMaybe<TString> continuationToken = msg->Record .GetContinuationToken ();
555
+
556
+ Y_ABORT_UNLESS (continuationToken);
557
+
558
+ NKikimrTxDataShard::TReadContinuationToken token;
559
+ Y_ABORT_UNLESS (token.ParseFromString (*continuationToken), " Failed to parse continuation token" );
560
+
561
+ // Save continuation token in case we will have to retry on error, but for now
562
+ // we just wait for the next batch of results.
563
+ it->second .FirstUnprocessedQuery = token.GetFirstUnprocessedQuery ();
564
+ ReadsInFlight++;
565
+ }
543
566
}
544
- Y_ABORT_UNLESS (msg->Record .HasFinished () && msg->Record .GetFinished ());
545
567
LOG_DEBUG_S (TlsActivationContext->AsActorContext (), NKikimrServices::RPC_REQUEST, " TReadRowsRPC TEvReadResult RowsCount: " << msg->GetRowsCount ());
546
568
547
569
EvReadResults.emplace_back (ev->Release ().Release ());
@@ -761,7 +783,7 @@ class TReadRowsRPC : public TActorBootstrapped<TReadRowsRPC> {
761
783
};
762
784
TVector<TColumnMeta> RequestedColumnsMeta;
763
785
764
- std::map<ui64, std::vector<TOwnedCellVec>> ShardIdToKeys ;
786
+ std::map<ui64, TShardReadState> ShardIdToReadState ;
765
787
std::vector<std::unique_ptr<TEvDataShard::TEvReadResult>> EvReadResults;
766
788
// TEvRead interface
767
789
ui64 ReadsInFlight = 0 ;
0 commit comments