private void TestRebalance( IShardAllocationStrategy allocationStrategy, IImmutableDictionary <IActorRef, IImmutableList <string> > allocations, ImmutableList <IImmutableDictionary <IActorRef, IImmutableList <string> > > steps, int maxSteps) { var round = steps.Count; var rebalanceResult = allocationStrategy.Rebalance(allocations, ImmutableHashSet <string> .Empty).Result; var newAllocations = LeastShardAllocationStrategySpec.AfterRebalance(allocationStrategy, allocations, rebalanceResult); LeastShardAllocationStrategySpec.CountShards(newAllocations).Should().Be(LeastShardAllocationStrategySpec.CountShards(allocations), $"test {allocationStrategy}[{ string.Join(", ", LeastShardAllocationStrategySpec.CountShardsPerRegion(allocations))}]: "); var min = LeastShardAllocationStrategySpec.CountShardsPerRegion(newAllocations).Min(); var max = LeastShardAllocationStrategySpec.CountShardsPerRegion(newAllocations).Max(); var diff = max - min; var newSteps = steps.Add(newAllocations); if (diff <= 1) { if (round >= 3 && maxSteps <= 10) { // Should be very rare (I have not seen it) Sys.Log.Info($"rebalance solved in round {round}, [{string.Join(" => ", newSteps.Select(step => string.Join(", ", LeastShardAllocationStrategySpec.CountShardsPerRegion(step))))}]"); } } else if (round == maxSteps) { throw new AssertionFailedException($"Couldn't solve rebalance in $round rounds, [{string.Join(" => ", newSteps.Select(step => string.Join(", ", LeastShardAllocationStrategySpec.CountShardsPerRegion(step))))}]"); } else { TestRebalance(allocationStrategy, newAllocations, newSteps, maxSteps); } }
private void TestRebalance( IShardAllocationStrategy allocationStrategy, int maxRegions, int maxShardsPerRegion, int expectedMaxSteps) { foreach (var i in Enumerable.Range(1, iterationsPerTest)) { iteration += 1; var numberOfRegions = rnd.Next(maxRegions) + 1; var memberArray = Enumerable.Range(1, numberOfRegions).Select(n => LeastShardAllocationStrategySpec.NewUpMember("127.0.0.1", port: n)).ToArray(); clusterMembers = ImmutableSortedSet.Create(memberArray);//.toIndexedSeq: _ *); var regions = Enumerable.Range(1, numberOfRegions).Select(n => LeastShardAllocationStrategySpec.NewFakeRegion($"{iteration}-R{n}", memberArray[n - 1])); //var regions = Enumerable.Range(1, numberOfRegions).Select(n => Sys.ActorOf(Props.Empty, $"{iteration}-R{n}")).ToImmutableList(); var countPerRegion = regions.ToImmutableDictionary(region => region, region => rnd.Next(maxShardsPerRegion)); var allocations = CreateAllocations(countPerRegion); TestRebalance(allocationStrategy, allocations, ImmutableList.Create(allocations), expectedMaxSteps); foreach (var region in regions) { Sys.Stop(region); } } }
internal static IActorRef NewFakeRegion(string idForDebug, Member member) => LeastShardAllocationStrategySpec.NewFakeRegion(idForDebug, member);
internal static Member NewUpMember(string host, int port = 252525, AppVersion version = null) => LeastShardAllocationStrategySpec.NewUpMember(host, port, version);