@@ -4776,6 +4776,84 @@ Y_UNIT_TEST_SUITE(THiveTest) {
47764776 }
47774777 }
47784778
4779+ Y_UNIT_TEST (TestHiveBalancerUselessNeighbourMoves) {
4780+ // 7 tablets of same object, 3 nodes, one of nodes cannot run them
4781+ // distribution should be (4, 3, 0)
4782+ // this should trigger balancer, but not lead to any moves
4783+ static constexpr ui64 NUM_NODES = 3 ;
4784+ static constexpr ui64 NUM_TABLETS = 7 ;
4785+ TTestBasicRuntime runtime (NUM_NODES, false );
4786+ Setup (runtime, true , 1 , [](TAppPrepare& app) {
4787+ app.HiveConfig .SetTabletKickCooldownPeriod (0 );
4788+ app.HiveConfig .SetResourceChangeReactionPeriod (0 );
4789+ app.HiveConfig .SetMetricsWindowSize (1 );
4790+ });
4791+ const int nodeBase = runtime.GetNodeId (0 );
4792+ TActorId senderA = runtime.AllocateEdgeActor ();
4793+ const ui64 hiveTablet = MakeDefaultHiveID ();
4794+ const ui64 testerTablet = MakeTabletID (false , 1 );
4795+
4796+ auto getDistribution = [hiveTablet, nodeBase, senderA, &runtime]() -> std::array<std::vector<ui64>, NUM_NODES> {
4797+ std::array<std::vector<ui64>, NUM_NODES> nodeTablets = {};
4798+ {
4799+ runtime.SendToPipe (hiveTablet, senderA, new TEvHive::TEvRequestHiveInfo ());
4800+ TAutoPtr<IEventHandle> handle;
4801+ TEvHive::TEvResponseHiveInfo* response = runtime.GrabEdgeEventRethrow <TEvHive::TEvResponseHiveInfo>(handle);
4802+ for (const NKikimrHive::TTabletInfo& tablet : response->Record .GetTablets ()) {
4803+ UNIT_ASSERT_C (((int )tablet.GetNodeID () - nodeBase >= 0 ) && (tablet.GetNodeID () - nodeBase < NUM_NODES),
4804+ " nodeId# " << tablet.GetNodeID () << " nodeBase# " << nodeBase);
4805+ nodeTablets[tablet.GetNodeID () - nodeBase].push_back (tablet.GetTabletID ());
4806+ }
4807+ }
4808+ return nodeTablets;
4809+ };
4810+
4811+ CreateTestBootstrapper (runtime, CreateTestTabletInfo (hiveTablet, TTabletTypes::Hive), &CreateDefaultHive);
4812+
4813+ // wait for creation of nodes
4814+ {
4815+ TDispatchOptions options;
4816+ options.FinalEvents .emplace_back (TEvLocal::EvStatus, NUM_NODES);
4817+ runtime.DispatchEvents (options);
4818+ }
4819+
4820+ TTabletTypes::EType tabletType = TTabletTypes::Dummy;
4821+ std::vector<ui64> tablets;
4822+ tablets.reserve (NUM_TABLETS);
4823+ for (size_t i = 0 ; i < NUM_TABLETS; ++i) {
4824+ THolder<TEvHive::TEvCreateTablet> ev (new TEvHive::TEvCreateTablet (testerTablet, 100500 + i, tabletType, BINDED_CHANNELS));
4825+ ev->Record .SetObjectId (1 );
4826+ ev->Record .AddAllowedNodeIDs (nodeBase);
4827+ ev->Record .AddAllowedNodeIDs (nodeBase + 1 );
4828+ ui64 tabletId = SendCreateTestTablet (runtime, hiveTablet, testerTablet, std::move (ev), 0 , true );
4829+ MakeSureTabletIsUp (runtime, tabletId, 0 );
4830+ tablets.push_back (tabletId);
4831+ }
4832+
4833+ auto initialDistribution = getDistribution ();
4834+
4835+ for (auto tablet : tablets) {
4836+ THolder<TEvHive::TEvTabletMetrics> metrics = MakeHolder<TEvHive::TEvTabletMetrics>();
4837+ NKikimrHive::TTabletMetrics* metric = metrics->Record .AddTabletMetrics ();
4838+ metric->SetTabletID (tablet);
4839+ metric->MutableResourceUsage ()->SetCPU (0 );
4840+ metric->MutableResourceUsage ()->SetMemory (0 );
4841+
4842+ runtime.SendToPipe (hiveTablet, senderA, metrics.Release ());
4843+ }
4844+
4845+ {
4846+ TDispatchOptions options;
4847+ options.FinalEvents .emplace_back (NHive::TEvPrivate::EvBalancerOut);
4848+ runtime.DispatchEvents (options, TDuration::Seconds (10 ));
4849+ }
4850+
4851+ // Check that balancer moved no tablets
4852+ auto newDistribution = getDistribution ();
4853+
4854+ UNIT_ASSERT_EQUAL (initialDistribution, newDistribution);
4855+ }
4856+
47794857 Y_UNIT_TEST (TestHiveBalancerWithImmovableTablets) {
47804858 static constexpr ui64 TABLETS_PER_NODE = 10 ;
47814859 TTestBasicRuntime runtime (3 , false );
0 commit comments