@@ -585,6 +585,46 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
585
585
ToTabletSend.emplace_back (shardId, ui64 (BuildId), std::move (ev));
586
586
}
587
587
588
+ void SendKMeansLocalRequest (TShardIdx shardIdx, TIndexBuildInfo& buildInfo) {
589
+ Y_ASSERT (buildInfo.IsBuildVectorIndex ());
590
+ auto ev = MakeHolder<TEvDataShard::TEvLocalKMeansRequest>();
591
+ ev->Record .SetId (ui64 (BuildId));
592
+
593
+ auto path = TPath::Init (buildInfo.TablePathId , Self).Dive (buildInfo.IndexName );
594
+ if (buildInfo.KMeans .Level == 0 ) {
595
+ PathIdFromPathId (buildInfo.TablePathId , ev->Record .MutablePathId ());
596
+ } else {
597
+ PathIdFromPathId (path.Dive (buildInfo.KMeans .ReadFrom ())->PathId , ev->Record .MutablePathId ());
598
+ path.Rise ();
599
+ }
600
+ *ev->Record .MutableSettings () = std::get<NKikimrSchemeOp::TVectorIndexKmeansTreeDescription>(
601
+ buildInfo.SpecializedIndexDescription ).GetSettings ().settings ();
602
+ ev->Record .SetK (buildInfo.KMeans .K );
603
+ ev->Record .SetUpload (buildInfo.KMeans .GetUpload ());
604
+ ev->Record .SetState (NKikimrTxDataShard::TEvLocalKMeansRequest::SAMPLE);
605
+
606
+ ev->Record .SetDoneRounds (0 );
607
+ ev->Record .SetNeedsRounds (3 ); // TODO(mbkkt) should be configurable
608
+
609
+ ev->Record .SetParent (buildInfo.KMeans .Parent );
610
+ ev->Record .SetChild (buildInfo.KMeans .ChildBegin );
611
+
612
+ ev->Record .SetPostingName (path.Dive (buildInfo.KMeans .WriteTo ()).PathString ());
613
+ path.Rise ().Dive (NTableIndex::NTableVectorKmeansTreeIndex::LevelTable);
614
+ ev->Record .SetLevelName (path.PathString ());
615
+
616
+ ev->Record .SetEmbeddingColumn (buildInfo.IndexColumns [0 ]);
617
+ *ev->Record .MutableDataColumns () = {
618
+ buildInfo.DataColumns .begin (), buildInfo.DataColumns .end ()
619
+ };
620
+
621
+ auto shardId = CommonFillRecord (ev->Record , shardIdx, buildInfo);
622
+ ev->Record .SetSeed (ui64 (shardId));
623
+ LOG_D (" TTxBuildProgress: TEvLocalKMeansRequest: " << ev->Record .ShortDebugString ());
624
+
625
+ ToTabletSend.emplace_back (shardId, ui64 (BuildId), std::move (ev));
626
+ }
627
+
588
628
void SendBuildIndexRequest (TShardIdx shardIdx, TIndexBuildInfo& buildInfo) {
589
629
auto ev = MakeHolder<TEvDataShard::TEvBuildIndexCreateRequest>();
590
630
ev->Record .SetBuildIndexId (ui64 (BuildId));
@@ -719,10 +759,9 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
719
759
Y_ABORT (" Unreachable" );
720
760
}
721
761
}
722
- // TODO(mbkkt) enable detection of Local case
723
- // if (buildInfo.ToUploadShards.size() == 1 && buildInfo.DoneShardsSize == 0) {
724
- // buildInfo.KMeans.State = TIndexBuildInfo::TKMeans::Local;
725
- // }
762
+ if (buildInfo.DoneShards .empty () && buildInfo.ToUploadShards .size () == 1 ) {
763
+ buildInfo.KMeans .State = TIndexBuildInfo::TKMeans::Local;
764
+ }
726
765
}
727
766
728
767
bool SendKMeansSample (TIndexBuildInfo& buildInfo) {
@@ -739,6 +778,10 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
739
778
return SendToShards (buildInfo, [&](TShardIdx shardIdx) { SendKMeansReshuffleRequest (shardIdx, buildInfo); });
740
779
}
741
780
781
+ bool SendKMeansLocal (TIndexBuildInfo& buildInfo) {
782
+ return SendToShards (buildInfo, [&](TShardIdx shardIdx) { SendKMeansLocalRequest (shardIdx, buildInfo); });
783
+ }
784
+
742
785
bool SendVectorIndex (TIndexBuildInfo& buildInfo) {
743
786
switch (buildInfo.KMeans .State ) {
744
787
case TIndexBuildInfo::TKMeans::Sample:
@@ -748,9 +791,8 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
748
791
// return SendKMeansRecompute(buildInfo);
749
792
case TIndexBuildInfo::TKMeans::Reshuffle:
750
793
return SendKMeansReshuffle (buildInfo);
751
- // TODO(mbkkt)
752
- // case TIndexBuildInfo::TKMeans::Local:
753
- // return SendKMeansLocal(buildInfo);
794
+ case TIndexBuildInfo::TKMeans::Local:
795
+ return SendKMeansLocal (buildInfo);
754
796
}
755
797
return true ;
756
798
}
@@ -1357,6 +1399,131 @@ struct TSchemeShard::TIndexBuilder::TTxReplySampleK: public TSchemeShard::TIndex
1357
1399
}
1358
1400
};
1359
1401
1402
+ struct TSchemeShard ::TIndexBuilder::TTxReplyLocalKMeans: public TSchemeShard::TIndexBuilder::TTxReply {
1403
+ private:
1404
+ TEvDataShard::TEvLocalKMeansResponse::TPtr Local;
1405
+
1406
+ public:
1407
+ explicit TTxReplyLocalKMeans (TSelf* self, TEvDataShard::TEvLocalKMeansResponse::TPtr& local)
1408
+ : TTxReply(self)
1409
+ , Local(local)
1410
+ {
1411
+ }
1412
+
1413
+ bool DoExecute (TTransactionContext& txc, const TActorContext& ctx) override {
1414
+ auto & record = Local->Get ()->Record ;
1415
+
1416
+ LOG_I (" TTxReply : TEvLocalKMeansResponse, Id# " << record.GetId ());
1417
+
1418
+ const auto buildId = TIndexBuildId (record.GetId ());
1419
+ const auto * buildInfoPtr = Self->IndexBuilds .FindPtr (buildId);
1420
+ if (!buildInfoPtr) {
1421
+ return true ;
1422
+ }
1423
+ auto & buildInfo = *buildInfoPtr->Get ();
1424
+ LOG_D (" TTxReply : TEvLocalKMeansResponse"
1425
+ << " , TIndexBuildInfo: " << buildInfo
1426
+ << " , record: " << record.ShortDebugString ());
1427
+
1428
+ TTabletId shardId = TTabletId (record.GetTabletId ());
1429
+ if (!Self->TabletIdToShardIdx .contains (shardId)) {
1430
+ return true ;
1431
+ }
1432
+
1433
+ TShardIdx shardIdx = Self->TabletIdToShardIdx .at (shardId);
1434
+ if (!buildInfo.Shards .contains (shardIdx)) {
1435
+ return true ;
1436
+ }
1437
+
1438
+ switch (const auto state = buildInfo.State ; state) {
1439
+ case TIndexBuildInfo::EState::Filling:
1440
+ {
1441
+ TIndexBuildInfo::TShardStatus& shardStatus = buildInfo.Shards .at (shardIdx);
1442
+
1443
+ auto actualSeqNo = std::pair<ui64, ui64>(Self->Generation (), shardStatus.SeqNoRound );
1444
+ auto recordSeqNo = std::pair<ui64, ui64>(record.GetRequestSeqNoGeneration (), record.GetRequestSeqNoRound ());
1445
+
1446
+ if (actualSeqNo != recordSeqNo) {
1447
+ LOG_D (" TTxReply : TEvLocalKMeansResponse"
1448
+ << " ignore progress message by seqNo"
1449
+ << " , TIndexBuildInfo: " << buildInfo
1450
+ << " , actual seqNo for the shard " << shardId << " (" << shardIdx << " ) is: " << Self->Generation () << " :" << shardStatus.SeqNoRound
1451
+ << " , record: " << record.ShortDebugString ());
1452
+ Y_ABORT_UNLESS (actualSeqNo > recordSeqNo);
1453
+ return true ;
1454
+ }
1455
+
1456
+ TBillingStats stats{record.GetUploadRows (), record.GetUploadBytes (), record.GetReadRows (), record.GetReadBytes ()};
1457
+ shardStatus.Processed += stats;
1458
+ buildInfo.Processed += stats;
1459
+
1460
+ NYql::TIssues issues;
1461
+ NYql::IssuesFromMessage (record.GetIssues (), issues);
1462
+ shardStatus.DebugMessage = issues.ToString ();
1463
+
1464
+ NIceDb::TNiceDb db (txc.DB );
1465
+ shardStatus.Status = record.GetStatus ();
1466
+
1467
+ switch (shardStatus.Status ) {
1468
+ case NKikimrIndexBuilder::EBuildStatus::DONE:
1469
+ if (buildInfo.InProgressShards .erase (shardIdx)) {
1470
+ buildInfo.DoneShards .emplace_back (shardIdx);
1471
+ }
1472
+ break ;
1473
+ case NKikimrIndexBuilder::EBuildStatus::ABORTED:
1474
+ // datashard gracefully rebooted, reschedule shard
1475
+ if (buildInfo.InProgressShards .erase (shardIdx)) {
1476
+ buildInfo.ToUploadShards .emplace_front (shardIdx);
1477
+ }
1478
+ break ;
1479
+ case NKikimrIndexBuilder::EBuildStatus::BUILD_ERROR:
1480
+ case NKikimrIndexBuilder::EBuildStatus::BAD_REQUEST:
1481
+ buildInfo.Issue += TStringBuilder ()
1482
+ << " One of the shards report " << shardStatus.Status
1483
+ << " at Filling stage, process has to be canceled"
1484
+ << " , shardId: " << shardId
1485
+ << " , shardIdx: " << shardIdx;
1486
+ Self->PersistBuildIndexIssue (db, buildInfo);
1487
+ ChangeState (buildInfo.Id , TIndexBuildInfo::EState::Rejection_Applying);
1488
+
1489
+ Progress (buildId);
1490
+ return true ;
1491
+ case NKikimrIndexBuilder::EBuildStatus::INVALID:
1492
+ case NKikimrIndexBuilder::EBuildStatus::ACCEPTED:
1493
+ case NKikimrIndexBuilder::EBuildStatus::IN_PROGRESS:
1494
+ Y_ABORT (" Unreachable" );
1495
+ }
1496
+ Self->PersistBuildIndexUploadProgress (db, buildId, shardIdx, shardStatus);
1497
+ Self->IndexBuildPipes .Close (buildId, shardId, ctx);
1498
+ Progress (buildId);
1499
+ break ;
1500
+ }
1501
+ case TIndexBuildInfo::EState::AlterMainTable:
1502
+ case TIndexBuildInfo::EState::Invalid:
1503
+ case TIndexBuildInfo::EState::Locking:
1504
+ case TIndexBuildInfo::EState::GatheringStatistics:
1505
+ case TIndexBuildInfo::EState::Initiating:
1506
+ case TIndexBuildInfo::EState::DropBuild:
1507
+ case TIndexBuildInfo::EState::CreateBuild:
1508
+ case TIndexBuildInfo::EState::Applying:
1509
+ case TIndexBuildInfo::EState::Unlocking:
1510
+ case TIndexBuildInfo::EState::Done:
1511
+ Y_FAIL_S (" Unreachable " << Name (state));
1512
+ case TIndexBuildInfo::EState::Cancellation_Applying:
1513
+ case TIndexBuildInfo::EState::Cancellation_Unlocking:
1514
+ case TIndexBuildInfo::EState::Cancelled:
1515
+ case TIndexBuildInfo::EState::Rejection_Applying:
1516
+ case TIndexBuildInfo::EState::Rejection_Unlocking:
1517
+ case TIndexBuildInfo::EState::Rejected:
1518
+ LOG_D (" TTxReply : TEvLocalKMeansResponse"
1519
+ << " superfluous message " << record.ShortDebugString ());
1520
+ break ;
1521
+ }
1522
+
1523
+ return true ;
1524
+ }
1525
+ };
1526
+
1360
1527
struct TSchemeShard ::TIndexBuilder::TTxReplyReshuffleKMeans: public TSchemeShard::TIndexBuilder::TTxReply {
1361
1528
private:
1362
1529
TEvDataShard::TEvReshuffleKMeansResponse::TPtr Reshuffle;
@@ -2112,6 +2279,10 @@ ITransaction* TSchemeShard::CreateTxReply(TEvDataShard::TEvReshuffleKMeansRespon
2112
2279
return new TIndexBuilder::TTxReplyReshuffleKMeans (this , reshuffle);
2113
2280
}
2114
2281
2282
+ ITransaction* TSchemeShard::CreateTxReply (TEvDataShard::TEvLocalKMeansResponse::TPtr& local) {
2283
+ return new TIndexBuilder::TTxReplyLocalKMeans (this , local);
2284
+ }
2285
+
2115
2286
ITransaction* TSchemeShard::CreateTxReply (TEvIndexBuilder::TEvUploadSampleKResponse::TPtr& upload) {
2116
2287
return new TIndexBuilder::TTxReplyUpload (this , upload);
2117
2288
}
0 commit comments