public void ClusterNodesMustBeAbleToRestartAndJoinAgain()
{
Within(TimeSpan.FromSeconds(60), () =>
{
// secondSystem is a separate ActorSystem, to be able to simulate restart
// we must transfer its address to first
RunOn(() =>
{
Sys.ActorOf(c => c.Receive<UniqueAddress>((address, ctx) =>
{
_secondUniqueAddress = address;
ctx.Sender.Tell("ok");
}), "address-receiver");
EnterBarrier("second-address-receiver-ready");
}, _config.First, _config.Third);
RunOn(() =>
{
EnterBarrier("second-address-receiver-ready");
_secondUniqueAddress = Cluster.Get(_secondSystem.Value).SelfUniqueAddress;
foreach (var r in new[] {GetAddress(_config.First), GetAddress(_config.Third)})
{
Sys.ActorSelection(new RootActorPath(r) / "user" / "address-receiver").Tell(_secondUniqueAddress);
ExpectMsg("ok", TimeSpan.FromSeconds(5));
}
}, _config.Second);
EnterBarrier("second-address-transfered");
// now we can join first, secondSystem, third together
RunOn(() =>
{
Cluster.JoinSeedNodes(SeedNodes);
AwaitMembersUp(3);
}, _config.First, _config.Third);
RunOn(() =>
{
Cluster.Get(_secondSystem.Value).JoinSeedNodes(SeedNodes);
AwaitAssert(() => Assert.Equal(3, Cluster.Get(_secondSystem.Value).ReadView.Members.Count));
AwaitAssert(() => Assert.True(Cluster.Get(_secondSystem.Value).ReadView.Members.Select(x => x.Status).All(s => s == MemberStatus.Up)));
}, _config.Second);
EnterBarrier("started");
// shutdown _secondSystem
RunOn(() =>
{
// send system message just before shutdown
_secondSystem.Value.ActorOf(Props.Create(() => new Watcher(GetAddress(_config.First), TestActor)),
"testWatcher");
ExpectMsg<Done>();
Shutdown(_secondSystem.Value, Remaining);
}, _config.Second);
EnterBarrier("second-shutdown");
// then immediately start restartedSecondSystem, which has the same address as secondSystem
RunOn(() =>
{
Cluster.Get(_secondRestartedSystem.Value).JoinSeedNodes(SeedNodes);
AwaitAssert(() => Assert.Equal(3, Cluster.Get(_secondRestartedSystem.Value).ReadView.Members.Count));
AwaitAssert(() => Assert.True(Cluster.Get(_secondRestartedSystem.Value).ReadView.Members.Select(x => x.Status).All(s => s == MemberStatus.Up)));
}, _config.Second);
RunOn(() =>
{
AwaitAssert(() =>
{
Assert.Equal(3, Cluster.Get(Sys).ReadView.Members.Count);
Assert.True(
Cluster.Get(Sys)
.ReadView.Members.Any(m => m.Address.Equals(SecondUniqueAddress.Address) && m.UniqueAddress.Uid != SecondUniqueAddress.Uid));
});
}, _config.First, _config.Third);
EnterBarrier("second-restarted");
});
}
}