|
7 | 7 |
|
8 | 8 | using System; |
9 | 9 | using System.Collections.Generic; |
| 10 | +using System.Linq; |
10 | 11 | using System.Net; |
| 12 | +using System.Threading.Tasks; |
11 | 13 | using Akka.Actor; |
12 | 14 | using Akka.TestKit; |
| 15 | +using Akka.Util; |
13 | 16 | using Xunit; |
14 | 17 |
|
15 | 18 | namespace Akka.Remote.TestKit.Tests |
@@ -48,6 +51,40 @@ public void Controller_must_publish_its_nodes() |
48 | 51 | ExpectMsg<Terminated>(); |
49 | 52 | }, TimeSpan.FromSeconds(20)); |
50 | 53 | } |
| 54 | + |
| 55 | + [Fact(DisplayName = "Controller should keep a re-registered node when its previous connection reports a disconnect")] |
| 56 | + public async Task Controller_must_keep_a_re_registered_node_when_the_previous_connection_disconnects() |
| 57 | + { |
| 58 | + var address = Address.Parse("akka://sys"); |
| 59 | + var c = Sys.ActorOf(Props.Create(() => new Controller(1, new IPEndPoint(IPAddress.Loopback, 0)))); |
| 60 | + var oldConnection = CreateTestProbe(); |
| 61 | + var newConnection = CreateTestProbe(); |
| 62 | + |
| 63 | + oldConnection.Send(c, new Controller.NodeInfo(A, address, oldConnection.Ref)); |
| 64 | + await oldConnection.ExpectMsgAsync<ToClient<Done>>(); |
| 65 | + |
| 66 | + // Tear the node down the way TestConductor.Shutdown does, then let it come back on a |
| 67 | + // fresh connection under the same role, the way StartNewSystem does. |
| 68 | + c.Tell(new Terminate(A, new Left<bool, int>(true))); |
| 69 | + await oldConnection.ExpectMsgAsync<ToClient<TerminateMsg>>(); |
| 70 | + |
| 71 | + newConnection.Send(c, new Controller.NodeInfo(A, address, newConnection.Ref)); |
| 72 | + await newConnection.ExpectMsgAsync<ToClient<Done>>(); |
| 73 | + |
| 74 | + // The connection that has already been replaced now reports its disconnect. It must |
| 75 | + // not evict the registration that replaced it. |
| 76 | + oldConnection.Send(c, new Controller.ClientDisconnected(A)); |
| 77 | + |
| 78 | + c.Tell(Controller.GetNodes.Instance); |
| 79 | + var nodes = await ExpectMsgAsync<IEnumerable<RoleName>>(); |
| 80 | + Assert.Contains(A, nodes.ToList()); |
| 81 | + |
| 82 | + // The barrier coordinator has to still know the node as well, otherwise its arrivals |
| 83 | + // are ignored and every later barrier stalls. |
| 84 | + newConnection.Send(c, new EnterBarrier("after-restart", null, A)); |
| 85 | + var result = await newConnection.ExpectMsgAsync<ToClient<BarrierResult>>(); |
| 86 | + Assert.True(result.Msg.Success); |
| 87 | + } |
51 | 88 | } |
52 | 89 | } |
53 | 90 |
|
0 commit comments