public void TestReconnectAllowedFlags() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; Object testLock = new Object(); opts.ClosedEventHandler = (sender, args) => { lock (testLock) { Monitor.Pulse(testLock); } }; using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { lock (testLock) { ns.Shutdown(); Assert.False(Monitor.Wait(testLock, 1000)); } Assert.True(c.State == ConnState.RECONNECTING); c.Opts.ClosedEventHandler = null; } } }
public void TestBasicReconnectFunctionality() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; AutoResetEvent Disconnected = new AutoResetEvent(false); AutoResetEvent Reconnected = new AutoResetEvent(false); AutoResetEvent MessageArrived = new AutoResetEvent(false); Object testLock = new Object(); Object msgLock = new Object(); opts.DisconnectedEventHandler = (sender, args) => { Disconnected.Set(); }; opts.ReconnectedEventHandler = (sender, args) => { Reconnected.Set(); }; using (var ns1 = NATSServer.Create(Context.Server1.Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { using (var s = c.SubscribeAsync("foo")) { s.MessageHandler += (sender, args) => { MessageArrived.Set(); }; s.Start(); c.Flush(); lock (testLock) { ns1.Shutdown(); Assert.True(Disconnected.WaitOne(100000)); } c.Publish("foo", Encoding.UTF8.GetBytes("Hello")); // restart the server. using (NATSServer.Create(Context.Server1.Port)) { Assert.True(Reconnected.WaitOne(20000)); Assert.True(c.Stats.Reconnects == 1); c.Flush(5000); Assert.True(MessageArrived.WaitOne(20000)); } } } } }
public void TestReconnectDisallowedFlags() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.AllowReconnect = false; Object testLock = new Object(); opts.ClosedEventHandler = (sender, args) => { lock (testLock) { Monitor.Pulse(testLock); } }; using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { lock (testLock) { ns.Shutdown(); Assert.True(Monitor.Wait(testLock, 1000)); } } } }
public void TestClose() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.AllowReconnect = true; opts.MaxReconnect = 60; using (NATSServer s1 = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { Assert.False(c.IsClosed()); s1.Shutdown(); Thread.Sleep(100); Assert.False(c.IsClosed(), string.Format("Invalid state, expecting not closed, received: {0}", c.State)); using (NATSServer s2 = NATSServer.Create(Context.Server1.Port)) { Thread.Sleep(1000); Assert.False(c.IsClosed()); c.Close(); Assert.True(c.IsClosed()); } } } }
public void TestReconnectWaitJitter() { AutoResetEvent reconnected = new AutoResetEvent(false); Stopwatch sw = new Stopwatch(); var opts = Context.GetTestOptions(Context.Server1.Port); opts.ReconnectWait = 100; opts.SetReconnectJitter(500, 0); opts.ReconnectedEventHandler = (obj, args) => { sw.Stop(); reconnected.Set(); }; using (var s = NATSServer.Create(Context.Server1.Port)) { // Create our client connections. using (new ConnectionFactory().CreateConnection(opts)) { sw.Start(); s.Bounce(50); Assert.True(reconnected.WaitOne(5000)); } } // We should wait at least the reconnect wait + random up to 500ms. // Account for a bit of variation since we rely on the reconnect // handler which is not invoked in place. long elapsed = sw.ElapsedMilliseconds; Assert.True(elapsed > 100); Assert.True(elapsed < 800); }
public void TestReconnectBufferBoundary() { AutoResetEvent disconnected = new AutoResetEvent(false); var opts = Context.GetTestOptions(Context.Server1.Port); opts.ReconnectBufferSize = 32; // 32 bytes opts.DisconnectedEventHandler = (obj, args) => { disconnected.Set(); }; EventHandler <MsgHandlerEventArgs> eh = (obj, args) => { /* NOOP */ }; using (var server = NATSServer.Create(Context.Server1.Port)) { using (var c = new ConnectionFactory().CreateConnection(opts)) { using (c.SubscribeAsync("foo", eh)) { server.Shutdown(); // wait until we're disconnected. Assert.True(disconnected.WaitOne(5000)); // PUB foo 25\r\n<...> = 30 so first publish should be OK, 2nd publish // should fail. byte[] payload = new byte[18]; c.Publish("foo", payload); Assert.Throws <NATSReconnectBufferException>(() => c.Publish("foo", payload)); c.Close(); } } } }
public void TestReconnectWaitBreakOnClose() { var opts = Context.GetTestOptions(Context.Server1.Port); opts.ReconnectWait = 30000; using (var s = NATSServer.Create(Context.Server1.Port)) { // Create our client connections. using (var c = new ConnectionFactory().CreateConnection(opts)) { Stopwatch sw = Stopwatch.StartNew(); s.Shutdown(); // Wait a bit for the reconnect loop to go into wait mode. Thread.Sleep(250); // Close the connection to break waiting c.Close(); sw.Stop(); // It should be around 400 ms max, but only need to check that // it's less than 30000. Assert.True(sw.ElapsedMilliseconds < 30000); } } }
public void TestReconnectAllowedFlags() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; AutoResetEvent Closed = new AutoResetEvent(false); AutoResetEvent Disconnected = new AutoResetEvent(false); opts.DisconnectedEventHandler = (sender, args) => Disconnected.Set(); opts.ClosedEventHandler = (sender, args) => Closed.Set(); using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { ns.Shutdown(); Assert.True(Disconnected.WaitOne(1000)); Assert.False(Closed.WaitOne(1000)); Assert.True(c.State == ConnState.RECONNECTING); c.Opts.ClosedEventHandler = null; } } }
public void TestServersOption() { ConnectionFactory cf = Context.ConnectionFactory; Options o = Context.GetTestOptions(); o.NoRandomize = true; o.Servers = Context.GetTestServersUrls(); Assert.ThrowsAny <NATSNoServersException>(() => cf.CreateConnection(o)); // Make sure we can connect to first server if running using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (var c = cf.CreateConnection(o)) { Assert.Equal(Context.Server1.Url, c.ConnectedUrl); c.Close(); } } // make sure we can connect to a non-first server. using (NATSServer.Create(Context.Server6.Port)) { using (var c = cf.CreateConnection(o)) { Assert.Equal(Context.Server6.Url, c.ConnectedUrl); c.Close(); } } }
public void TestBasicReconnectFunctionality() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; Object testLock = new Object(); Object msgLock = new Object(); opts.DisconnectedEventHandler = (sender, args) => { lock (testLock) { Monitor.Pulse(testLock); } }; opts.ReconnectedEventHandler = (sender, args) => { // NOOP }; NATSServer ns = NATSServer.Create(Context.Server1.Port); using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { IAsyncSubscription s = c.SubscribeAsync("foo"); s.MessageHandler += (sender, args) => { lock (msgLock) { Monitor.Pulse(msgLock); } }; s.Start(); c.Flush(); lock (testLock) { ns.Shutdown(); Assert.True(Monitor.Wait(testLock, 100000)); } c.Publish("foo", Encoding.UTF8.GetBytes("Hello")); // restart the server. using (ns = NATSServer.Create(Context.Server1.Port)) { lock (msgLock) { c.Flush(50000); Assert.True(Monitor.Wait(msgLock, 10000)); } Assert.True(c.Stats.Reconnects == 1); } } }
public void TestUserPassTokenOptions() { using (NATSServer.Create(Context.Server1.Port, $"--auth foo")) { var opts = Context.GetTestOptions(Context.Server1.Port); opts.Token = "foo"; var c = Context.ConnectionFactory.CreateConnection(opts); c.Close(); opts.Token = "garbage"; Assert.Throws <NATSConnectionException>(() => { Context.ConnectionFactory.CreateConnection(opts); }); } using (NATSServer.Create(Context.Server1.Port, $"--user foo --pass b@r")) { var opts = Context.GetTestOptions(Context.Server1.Port); opts.User = "******"; opts.Password = "******"; var c = Context.ConnectionFactory.CreateConnection(opts); c.Close(); opts.Password = "******"; Assert.Throws <NATSConnectionException>(() => { Context.ConnectionFactory.CreateConnection(opts); }); opts.User = "******"; opts.Password = "******"; Assert.Throws <NATSConnectionException>(() => { Context.ConnectionFactory.CreateConnection(opts); }); } }
public void TestHotSpotReconnect() { int numClients = 10; SimClient[] clients = new SimClient[100]; Options opts = Context.GetTestOptions(); opts.Servers = Context.GetTestServersUrls(); NATSServer s1 = NATSServer.Create(Context.Server1.Port); Task[] waitgroup = new Task[numClients]; for (int i = 0; i < numClients; i++) { clients[i] = new SimClient(); waitgroup[i] = Task.Run(() => { clients[i].Connect(Context.GetTestServersUrls()); clients[i].waitForReconnect(); }); } NATSServer s3 = NATSServer.Create(Context.Server3.Port); NATSServer s5 = NATSServer.Create(Context.Server5.Port); s1.Shutdown(); Task.WaitAll(waitgroup); int s3Count = 0; int s5Count = 0; int unknown = 0; for (int i = 0; i < numClients; i++) { if (Context.Server3.Url.Equals(clients[i].ConnectedUrl)) { s3Count++; } else if (Context.Server5.Url.Equals(clients[i].ConnectedUrl)) { s5Count++; } else { unknown++; } } Assert.True(unknown == 0); int delta = Math.Abs(s3Count - s5Count); int range = numClients / 30; Assert.False(delta > range, string.Format("Connected clients to servers out of range: {0}/{0}", delta, range)); }
public void TestQueueSubsOnReconnect() { AutoResetEvent reconnectEvent = new AutoResetEvent(false); Options opts = getReconnectOptions(); opts.MaxReconnect = 32; string subj = "foo.bar"; string qgroup = "workers"; opts.ReconnectedEventHandler += (sender, args) => { reconnectEvent.Set(); }; using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { EventHandler <MsgHandlerEventArgs> eh = (sender, args) => { int seq = Convert.ToInt32(Encoding.UTF8.GetString(args.Message.Data)); lock (results) { if (results.ContainsKey(seq) == false) { results.Add(seq, true); } } }; // Create Queue Subscribers c.SubscribeAsync(subj, qgroup, eh); c.SubscribeAsync(subj, qgroup, eh); c.Flush(); sendAndCheckMsgs(c, subj, 10); ns.Shutdown(); // give the OS time to shut it down. Thread.Sleep(1000); // start back up using (NATSServer.Create(Context.Server1.Port)) { // wait for reconnect Assert.True(reconnectEvent.WaitOne(6000)); sendAndCheckMsgs(c, subj, 10); } } } }
public void TestAuthToken() { using (NATSServer s = NATSServer.Create(Context.Server1.Port, "-auth S3Cr3T0k3n!")) { connectAndFail(Context.Server1.Url); connectAndFail($"nats://invalid_token@localhost:{Context.Server1.Port}"); Context.ConnectionFactory.CreateConnection($"nats://S3Cr3T0k3n!@localhost:{Context.Server1.Port}").Close(); } }
public void TestProperReconnectDelay() { Object mu = new Object(); Options opts = Context.GetTestOptions(); opts.Servers = Context.GetTestServersUrls(); opts.NoRandomize = true; bool disconnectHandlerCalled = false; opts.DisconnectedEventHandler = (sender, args) => { opts.DisconnectedEventHandler = null; disconnectHandlerCalled = true; lock (mu) { disconnectHandlerCalled = true; Monitor.Pulse(mu); } }; bool closedCbCalled = false; opts.ClosedEventHandler = (sender, args) => { closedCbCalled = true; }; using (NATSServer s1 = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { lock (mu) { s1.Shutdown(); // wait for disconnect Assert.True(Monitor.Wait(mu, 10000)); // Wait, want to make sure we don't spin on //reconnect to non-existant servers. Thread.Sleep(1000); Assert.False(closedCbCalled); Assert.True(disconnectHandlerCalled); Assert.True(c.State == ConnState.RECONNECTING); } } } }
public void TestServerDiscoveredHandler() { IConnection c = null; ConnectionFactory cf = Context.ConnectionFactory; Options o = Context.GetTestOptions(); o.NoRandomize = true; o.Servers = Context.GetTestServersUrls(); bool serverDiscoveredCalled = false; o.ServerDiscoveredEventHandler += (sender, e) => { serverDiscoveredCalled = true; }; string seedServerArgs = $@"-p {Context.Server1.Port} -cluster {Context.ClusterServer1.Url}"; string secondClusterMemberArgs = $@"-p {Context.Server2.Port} -cluster {Context.ClusterServer2.Url} -routes {Context.ClusterServer1.Url}"; // create the seed server for a cluster... using (NATSServer ns1 = NATSServer.Create(seedServerArgs)) { // ...then connect to it... using (c = cf.CreateConnection(o)) { Assert.Equal(Context.Server1.Url, c.ConnectedUrl); // ...then while connected, start up a second server... using (NATSServer ns2 = NATSServer.Create(secondClusterMemberArgs)) { // ...waiting up to 30 seconds for the second server to start... for (int ii = 0; ii < 6; ii++) { Thread.Sleep(5000); // ...taking an early out if we detected the startup... if (serverDiscoveredCalled) { break; } } // ...and by then we should have received notification of // its awakening. Assert.True(serverDiscoveredCalled); } } } }
private void TestPingReconnect() { /// Work in progress int RECONNECTS = 4; Options opts = Context.GetTestOptions(); Object mu = new Object(); opts.Servers = Context.GetTestServersShortListUrls(); opts.NoRandomize = true; opts.ReconnectWait = 200; opts.PingInterval = 50; opts.MaxPingsOut = -1; opts.Timeout = 1000; Stopwatch disconnectedTimer = new Stopwatch(); opts.DisconnectedEventHandler = (sender, args) => { disconnectedTimer.Reset(); disconnectedTimer.Start(); }; opts.ReconnectedEventHandler = (sender, args) => { lock (mu) { args.Conn.Opts.MaxPingsOut = 500; disconnectedTimer.Stop(); Monitor.Pulse(mu); } }; using (NATSServer s1 = NATSServer.Create(Context.TestServersShortList[0].Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { s1.Shutdown(); for (int i = 0; i < RECONNECTS; i++) { lock (mu) { Assert.True(Monitor.Wait(mu, 100000)); } } } } }
public void TestCustomReconnectDelay() { AutoResetEvent ev = new AutoResetEvent(false); var opts = Context.GetTestOptions(Context.Server1.Port); opts.ReconnectDelayHandler = (obj, args) => ev.Set(); using (var s = NATSServer.Create(Context.Server1.Port)) { using (new ConnectionFactory().CreateConnection(opts)) { s.Shutdown(); Assert.True(ev.WaitOne(10000)); } } }
public void TestReconnectVerbose() { // an exception stops and fails the test. IConnection c = null; Object reconnectLock = new Object(); bool reconnected = false; Options opts = Context.GetTestOptions(Context.Server1.Port); opts.Verbose = true; opts.ReconnectedEventHandler += (sender, args) => { lock (reconnectLock) { reconnected = true; Monitor.Pulse(reconnectLock); } }; using (NATSServer s = NATSServer.Create(Context.Server1.Port)) { c = Context.ConnectionFactory.CreateConnection(opts); c.Flush(); // exit the block and enter a new server block - this // restarts the server. } using (NATSServer s = NATSServer.Create(Context.Server1.Port)) { lock (reconnectLock) { if (!reconnected) { Monitor.Wait(reconnectLock, 5000); } } c.Flush(); } }
public void TestReconnectVerbose() { // an exception stops and fails the test. Object reconnectLock = new Object(); bool reconnected = false; Options opts = Context.GetTestOptions(Context.Server1.Port); opts.Verbose = true; opts.ReconnectedEventHandler += (sender, args) => { lock (reconnectLock) { reconnected = true; Monitor.Pulse(reconnectLock); } }; using (NATSServer s = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { c.Flush(); s.Shutdown(); using (NATSServer.Create(Context.Server1.Port)) { lock (reconnectLock) { if (!reconnected) { Monitor.Wait(reconnectLock, 5000); } } c.Flush(); } } } }
public void TestReconnectBufferDisabled() { IConnection c; ISyncSubscription s; AutoResetEvent disconnected = new AutoResetEvent(false); AutoResetEvent reconnected = new AutoResetEvent(false); var opts = Context.GetTestOptions(Context.Server1.Port); opts.ReconnectBufferSize = Options.ReconnectBufferDisabled; opts.DisconnectedEventHandler = (obj, args) => { disconnected.Set(); }; opts.ReconnectedEventHandler = (obj, args) => { reconnected.Set(); }; using (var server = NATSServer.Create(Context.Server1.Port)) { // Create our client connections. c = new ConnectionFactory().CreateConnection(opts); s = c.SubscribeSync("foo"); // let the server shutdown via dispose } // wait until we're disconnected. Assert.True(disconnected.WaitOne(5000)); // Publish a message. Assert.Throws <NATSReconnectBufferException>(() => { c.Publish("foo", null); }); using (var server = NATSServer.Create(Context.Server1.Port)) { // wait for the client to reconnect. Assert.True(reconnected.WaitOne(20000)); // Check that we do not receive a message. Assert.Throws <NATSTimeoutException>(() => { s.NextMessage(1000); }); } c.Close(); c.Dispose(); }
public void TestReconnectAllowedFlags() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; AutoResetEvent Closed = new AutoResetEvent(false); AutoResetEvent Disconnected = new AutoResetEvent(false); var sw = new Stopwatch(); opts.DisconnectedEventHandler = (sender, args) => { _testOutputHelper.WriteLine($"Disconnected event handler invoked after: {sw.ElapsedMilliseconds}ms"); Disconnected.Set(); }; opts.ClosedEventHandler = (sender, args) => { _testOutputHelper.WriteLine($"Closed event handler invoked after: {sw.ElapsedMilliseconds}ms"); Closed.Set(); }; opts.ReconnectedEventHandler = (_, __) => { _testOutputHelper.WriteLine($"Reconnect event handler invoked after: {sw.ElapsedMilliseconds}ms"); }; using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { sw.Start(); ns.Shutdown(); Assert.True(Disconnected.WaitOne(1000), "Disconnected event did not receive a signal"); Assert.False(Closed.WaitOne(1000), "Closed event did receive a signal"); Assert.True(c.State == ConnState.RECONNECTING, $"Expected {ConnState.RECONNECTING} but got {c.State} after {sw.ElapsedMilliseconds} ms"); c.Opts.ClosedEventHandler = null; } } }
public void TestProperFalloutAfterMaxAttempts() { Options opts = Context.GetTestOptions(); Object dmu = new Object(); Object cmu = new Object(); opts.Servers = Context.GetTestServersShortListUrls(); opts.NoRandomize = true; opts.MaxReconnect = 2; opts.ReconnectWait = 25; // millis opts.Timeout = 500; bool disconnectHandlerCalled = false; opts.DisconnectedEventHandler = (sender, args) => { lock (dmu) { disconnectHandlerCalled = true; Monitor.Pulse(dmu); } }; bool closedHandlerCalled = false; opts.ClosedEventHandler = (sender, args) => { lock (cmu) { closedHandlerCalled = true; Monitor.Pulse(cmu); } }; using (NATSServer s1 = NATSServer.Create(Context.TestServersShortList[0].Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { s1.Shutdown(); lock (dmu) { if (!disconnectHandlerCalled) { Assert.True(Monitor.Wait(dmu, 20000)); } } lock (cmu) { if (!closedHandlerCalled) { Assert.True(Monitor.Wait(cmu, 60000)); } } Assert.True(disconnectHandlerCalled); Assert.True(closedHandlerCalled); Assert.True(c.IsClosed()); } } }
public void TestProperFalloutAfterMaxAttemptsWithAuthMismatch() { Options opts = Context.GetTestOptions(); Object dmu = new Object(); Object cmu = new Object(); opts.Servers = new [] { Context.Server8.Url, Context.Server1.Url }; opts.NoRandomize = true; opts.MaxReconnect = 2; opts.ReconnectWait = 25; // millis opts.Timeout = 1000; bool disconnectHandlerCalled = false; opts.DisconnectedEventHandler = (sender, args) => { lock (dmu) { disconnectHandlerCalled = true; Monitor.Pulse(dmu); } }; bool closedHandlerCalled = false; opts.ClosedEventHandler = (sender, args) => { lock (cmu) { closedHandlerCalled = true; Monitor.Pulse(cmu); } }; using (NATSServer s1 = NATSServer.Create(Context.Server8.Port), s2 = NATSServer.CreateWithConfig(Context.Server1.Port, "tls_verify.conf")) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { s1.Shutdown(); lock (dmu) { if (!disconnectHandlerCalled) { Assert.True(Monitor.Wait(dmu, 20000)); } } lock (cmu) { if (!closedHandlerCalled) { Assert.True(Monitor.Wait(cmu, 600000)); } } Assert.True(c.Stats.Reconnects != opts.MaxReconnect); Assert.True(disconnectHandlerCalled); Assert.True(closedHandlerCalled); Assert.True(c.IsClosed()); } } }
public void TestTimeoutOnNoServers() { Options opts = Context.GetTestOptions(); Object dmu = new Object(); Object cmu = new Object(); opts.Servers = Context.GetTestServersShortListUrls(); opts.NoRandomize = true; opts.MaxReconnect = 2; opts.ReconnectWait = 100; // millis bool disconnectHandlerCalled = false; bool closedHandlerCalled = false; opts.DisconnectedEventHandler = (sender, args) => { lock (dmu) { disconnectHandlerCalled = true; Monitor.Pulse(dmu); } }; opts.ClosedEventHandler = (sender, args) => { lock (cmu) { closedHandlerCalled = true; Monitor.Pulse(cmu); } }; using (NATSServer s1 = NATSServer.Create(Context.TestServersShortList[0].Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { s1.Shutdown(); lock (dmu) { if (!disconnectHandlerCalled) { Assert.True(Monitor.Wait(dmu, 20000)); } } Stopwatch sw = new Stopwatch(); sw.Start(); lock (cmu) { if (!closedHandlerCalled) { Assert.True(Monitor.Wait(cmu, 60000)); } } sw.Stop(); int expected = opts.MaxReconnect * opts.ReconnectWait; // .NET has long connect times, so revisit this after // a connect timeout has been added. //Assert.IsTrue(sw.ElapsedMilliseconds < (expected + 500)); Assert.True(disconnectHandlerCalled); Assert.True(closedHandlerCalled); Assert.True(c.IsClosed()); } } }
public void TestBasicClusterReconnect() { Options opts = Context.GetTestOptions(); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; opts.NoRandomize = true; opts.Servers = new [] { Context.Server1.Url, Context.Server3.Url }; Object disconnectLock = new Object(); opts.DisconnectedEventHandler += (sender, args) => { // Suppress any additional calls opts.DisconnectedEventHandler = null; lock (disconnectLock) { Monitor.Pulse(disconnectLock); } }; Object reconnectLock = new Object(); opts.ReconnectedEventHandler = (sender, args) => { // Suppress any additional calls lock (reconnectLock) { Monitor.Pulse(reconnectLock); } }; opts.Timeout = 1000; using (NATSServer s1 = NATSServer.Create(Context.Server1.Port), s2 = NATSServer.Create(Context.Server3.Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { Stopwatch reconnectSw = new Stopwatch(); lock (disconnectLock) { s1.Shutdown(); Assert.True(Monitor.Wait(disconnectLock, 20000)); } reconnectSw.Start(); lock (reconnectLock) { Assert.True(Monitor.Wait(reconnectLock, 20000)); } Assert.Equal(c.ConnectedUrl, Context.Server3.Url); reconnectSw.Stop(); // Make sure we did not wait on reconnect for default time. // Reconnect should be fast since it will be a switch to the // second server and not be dependent on server restart time. // TODO: .NET connect timeout is exceeding long compared to // GO's. Look shortening it, or living with it. //if (reconnectSw.ElapsedMilliseconds > opts.ReconnectWait) //{ // Assert.Fail("Reconnect time took to long: {0} millis.", // reconnectSw.ElapsedMilliseconds); //} } } }
public void TestIsReconnectingAndStatus() { bool disconnected = false; object disconnectedLock = new object(); bool reconnected = false; object reconnectedLock = new object(); Options opts = Context.GetTestOptions(Context.Server1.Port); opts.AllowReconnect = true; opts.MaxReconnect = 10000; opts.ReconnectWait = 100; opts.DisconnectedEventHandler += (sender, args) => { lock (disconnectedLock) { disconnected = true; Monitor.Pulse(disconnectedLock); } }; opts.ReconnectedEventHandler += (sender, args) => { lock (reconnectedLock) { reconnected = true; Monitor.Pulse(reconnectedLock); } }; using (NATSServer s = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { Assert.True(c.State == ConnState.CONNECTED); Assert.True(c.IsReconnecting() == false); s.Shutdown(); lock (disconnectedLock) { if (!disconnected) { Assert.True(Monitor.Wait(disconnectedLock, 10000)); } } Assert.True(c.State == ConnState.RECONNECTING); Assert.True(c.IsReconnecting() == true); // restart the server using (NATSServer.Create(Context.Server1.Port)) { lock (reconnectedLock) { // may have reconnected, if not, wait if (!reconnected) { Assert.True(Monitor.Wait(reconnectedLock, 10000)); } } Assert.True(c.IsReconnecting() == false); Assert.True(c.State == ConnState.CONNECTED); c.Close(); } Assert.True(c.IsReconnecting() == false); Assert.True(c.State == ConnState.CLOSED); } } }
public void TestExtendedReconnectFunctionality() { Options opts = getReconnectOptions(); Object msgLock = new Object(); AutoResetEvent disconnectedEvent = new AutoResetEvent(false); AutoResetEvent reconnectedEvent = new AutoResetEvent(false); opts.DisconnectedEventHandler = (sender, args) => { disconnectedEvent.Set(); }; opts.ReconnectedEventHandler = (sender, args) => { reconnectedEvent.Set(); }; byte[] payload = Encoding.UTF8.GetBytes("bar"); using (var ns1 = NATSServer.Create(Context.Server1.Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { using (var s1 = c.SubscribeAsync("foo")) { s1.MessageHandler += incrReceivedMessageHandler; using (var s2 = c.SubscribeAsync("foobar")) { s2.MessageHandler += incrReceivedMessageHandler; s1.Start(); s2.Start(); received = 0; c.Publish("foo", payload); c.Flush(); ns1.Shutdown(); // server is stopped here. Assert.True(disconnectedEvent.WaitOne(20000)); // subscribe to bar while connected. using (var s3 = c.SubscribeAsync("bar")) { s3.MessageHandler += incrReceivedMessageHandler; s3.Start(); // Unsub foobar while disconnected s2.Unsubscribe(); c.Publish("foo", payload); c.Publish("bar", payload); // server is restarted here... using (NATSServer.Create(Context.Server1.Port)) { // wait for reconnect Assert.True(reconnectedEvent.WaitOne(60000)); c.Publish("foobar", payload); c.Publish("foo", payload); using (IAsyncSubscription s4 = c.SubscribeAsync("done")) { AutoResetEvent doneEvent = new AutoResetEvent(false); s4.MessageHandler += (sender, args) => { doneEvent.Set(); }; s4.Start(); c.Publish("done", payload); Assert.True(doneEvent.WaitOne(4000)); } } // NATSServer } } } Assert.Equal(4, received); } } }