public void LeastShardAllocationStrategy_should_rebalance_from_region_with_most_number_of_shards() { var allocations = new Dictionary <IActorRef, IImmutableList <string> > { { _regionA, new [] { "shard1" }.ToImmutableList() }, { _regionB, new [] { "shard2", "shard3" }.ToImmutableList() }, { _regionC, ImmutableList <string> .Empty } }.ToImmutableDictionary(); // so far regionB has 2 shards and regionC has 0 shards, but the diff is less than rebalanceThreshold var r1 = _allocationStrategy.Rebalance(allocations, ImmutableHashSet <string> .Empty).Result; r1.Count.Should().Be(0); allocations = allocations.SetItem(_regionB, new[] { "shard2", "shard3", "shard4" }.ToImmutableList()); var r2 = _allocationStrategy.Rebalance(allocations, ImmutableHashSet <string> .Empty).Result; r2.Should().BeEquivalentTo(new[] { "shard2", "shard3" }); var r3 = _allocationStrategy.Rebalance(allocations, ImmutableHashSet.Create("shard4")).Result; r3.Count.Should().Be(0); allocations = allocations.SetItem(_regionA, new[] { "shard1", "shard5", "shard6" }.ToImmutableList()); var r4 = _allocationStrategy.Rebalance(allocations, ImmutableHashSet.Create("shard1")).Result; r4.Should().BeEquivalentTo(new[] { "shard2" }); }
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); } }
public void LeastShardAllocationStrategy_should_reallocate_from_region_with_most_number_of_shards() { var allocations = new Dictionary <IActorRef, IImmutableList <string> > { { _regionA, new [] { "shard1" }.ToImmutableList() }, { _regionB, new [] { "shard2", "shard3" }.ToImmutableList() }, { _regionC, ImmutableList <string> .Empty } }.ToImmutableDictionary(); // so far regionB has 2 shards and regionC has 0 shards, but the diff is less than rebalanceThreshold var r1 = _allocationStrategy.Rebalance(allocations, ImmutableHashSet <string> .Empty).Result; Assert.Equal(r1.Count, 0); allocations = allocations.SetItem(_regionB, new[] { "shard2", "shard3", "shard4" }.ToImmutableList()); var r2 = _allocationStrategy.Rebalance(allocations, ImmutableHashSet <string> .Empty).Result; Assert.Equal(r2.Count, 1); Assert.Equal(r2.First(), "shard2"); var r3 = _allocationStrategy.Rebalance(allocations, ImmutableHashSet <string> .Empty.Add("shard4")).Result; Assert.Equal(r3.Count, 0); allocations = allocations.SetItem(_regionA, new[] { "shard1", "shard5", "shard6" }.ToImmutableList()); var r4 = _allocationStrategy.Rebalance(allocations, ImmutableHashSet <string> .Empty.Add("shard1")).Result; Assert.Equal(r4.Count, 1); Assert.Equal(r2.First(), "shard2"); }
private void HandleRebalanceTick() { if (_currentState.Regions.Count != 0) { var shardsTask = AllocationStrategy.Rebalance(_currentState.Regions, _rebalanceInProgress); if (shardsTask.IsCompleted && !shardsTask.IsFaulted) { ContinueRebalance(shardsTask.Result); } else { shardsTask.ContinueWith(t => !(t.IsFaulted || t.IsCanceled) ? new RebalanceResult(t.Result) : new RebalanceResult(Enumerable.Empty <ShardId>())) .PipeTo(Self); } } }
private void HandleRebalanceTick() { if (_currentState.Regions.Count != 0) { var shardsTask = AllocationStrategy.Rebalance(_currentState.Regions, _rebalanceInProgress); if (shardsTask.IsCompleted && !shardsTask.IsFaulted) { ContinueRebalance(shardsTask.Result); } else { shardsTask.ContinueWith(t => !(t.IsFaulted || t.IsCanceled) ? new RebalanceResult(t.Result) : new RebalanceResult(ImmutableHashSet <ShardId> .Empty), TaskContinuationOptions.ExecuteSynchronously) .PipeTo(Self); } } }