public async Task FarmDisconnectRaisesUncleanDisconnects() { EnableTracing(); // Each node shares the same bus but are indepenent servers var counters = new SignalR.Infrastructure.PerformanceCounterManager(); var configurationManager = new DefaultConfigurationManager(); var protectedData = new DefaultProtectedData(); using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000)) { var nodeCount = 3; var nodes = new List <ServerNode>(); for (int i = 0; i < nodeCount; i++) { nodes.Add(new ServerNode(bus)); } var timeout = TimeSpan.FromSeconds(5); foreach (var node in nodes) { var config = node.Resolver.Resolve <IConfigurationManager>(); config.DisconnectTimeout = TimeSpan.FromSeconds(6); IDependencyResolver resolver = node.Resolver; node.Server.Configure(app => { app.MapSignalR <FarmConnection>("/echo", new ConnectionConfiguration { Resolver = resolver }); resolver.Register(typeof(IProtectedData), () => protectedData); }); } var loadBalancer = new LoadBalancer(nodes.Select(f => f.Server).ToArray()); var transport = new Client.Transports.LongPollingTransport(loadBalancer); var connection = new Client.Connection("http://goo/echo"); await connection.Start(transport); for (int i = 0; i < nodes.Count; i++) { nodes[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)); await Task.Delay(TimeSpan.FromSeconds(1)); } ((Client.IConnection)connection).Disconnect(); await Task.Delay(TimeSpan.FromTicks(timeout.Ticks *nodes.Count)); Assert.Equal(0, FarmConnection.CleanDisconnectCount); Assert.Equal(3, FarmConnection.UncleanDisconnectCount); } }
public void FarmDisconnectOnlyRaisesEventOnce() { EnableTracing(); // Each node shares the same bus but are indepenent servers var counters = new SignalR.Infrastructure.PerformanceCounterManager(); var configurationManager = new DefaultConfigurationManager(); using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000)) { var nodeCount = 3; var nodes = new List <ServerNode>(); for (int i = 0; i < nodeCount; i++) { nodes.Add(new ServerNode(bus)); } var timeout = TimeSpan.FromSeconds(5); foreach (var node in nodes) { var config = node.Resolver.Resolve <IConfigurationManager>(); config.DisconnectTimeout = TimeSpan.FromSeconds(6); IDependencyResolver resolver = node.Resolver; node.Server.Configure(app => { app.MapConnection <FarmConnection>("/echo", new ConnectionConfiguration { Resolver = resolver }); }); } var loadBalancer = new LoadBalancer(nodes.Select(f => f.Server).ToArray()); var transport = new Client.Transports.LongPollingTransport(loadBalancer); var connection = new Client.Connection("http://goo/echo"); connection.Start(transport).Wait(); for (int i = 0; i < nodes.Count; i++) { nodes[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)); Thread.Sleep(TimeSpan.FromSeconds(1)); } ((Client.IConnection)connection).Disconnect(); Thread.Sleep(TimeSpan.FromTicks(timeout.Ticks * nodes.Count)); Assert.Equal(1, nodes.Sum(n => n.Connection.DisconnectCount)); } }
public async Task FarmDisconnectRaisesUncleanDisconnects() { // Each node shares the same bus but are independent servers const int nodeCount = 3; var counters = new PerformanceCounterManager(); var configurationManager = new DefaultConfigurationManager(); configurationManager.DisconnectTimeout = TimeSpan.FromSeconds(6); using (EnableDisposableTracing()) using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000)) using (var loadBalancer = new LoadBalancer(nodeCount)) { var broadcasters = new List <IConnection>(); var disconnectCounter = new DisconnectCounter(); loadBalancer.Configure(app => { var resolver = new DefaultDependencyResolver(); resolver.Register(typeof(IMessageBus), () => bus); resolver.Register(typeof(IConfigurationManager), () => configurationManager); resolver.Register(typeof(FarmConnection), () => new FarmConnection(disconnectCounter)); var connectionManager = resolver.Resolve <IConnectionManager>(); broadcasters.Add(connectionManager.GetConnectionContext <FarmConnection>().Connection); app.MapSignalR <FarmConnection>("/echo", new ConnectionConfiguration { Resolver = resolver }); }); var transport = new Client.Transports.LongPollingTransport(loadBalancer); var connection = new Client.Connection("http://goo/echo"); await connection.Start(transport); for (int i = 0; i < nodeCount; i++) { broadcasters[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)).Wait(); await Task.Delay(TimeSpan.FromSeconds(1)); } ((Client.IConnection)connection).Disconnect(); await Task.Delay(TimeSpan.FromTicks(TimeSpan.FromSeconds(5).Ticks *nodeCount)); Assert.Equal(0, disconnectCounter.CleanDisconnectCount); Assert.Equal(3, disconnectCounter.UncleanDisconnectCount); } }
public async Task FarmDisconnectRaisesUncleanDisconnects() { // Each node shares the same bus but are independent servers const int nodeCount = 3; var counters = new Infrastructure.PerformanceCounterManager(); var configurationManager = new DefaultConfigurationManager(); configurationManager.DisconnectTimeout = TimeSpan.FromSeconds(6); using (EnableDisposableTracing()) using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000)) using (var loadBalancer = new LoadBalancer(nodeCount)) { var broadcasters = new List<IConnection>(); var disconnectCounter = new DisconnectCounter(); loadBalancer.Configure(app => { var resolver = new DefaultDependencyResolver(); resolver.Register(typeof(IMessageBus), () => bus); resolver.Register(typeof(IConfigurationManager), () => configurationManager); resolver.Register(typeof(FarmConnection), () => new FarmConnection(disconnectCounter)); var connectionManager = resolver.Resolve<IConnectionManager>(); broadcasters.Add(connectionManager.GetConnectionContext<FarmConnection>().Connection); app.MapSignalR<FarmConnection>("/echo", new ConnectionConfiguration { Resolver = resolver }); }); var transport = new Client.Transports.LongPollingTransport(loadBalancer); var connection = new Client.Connection("http://goo/echo"); await connection.Start(transport); for (int i = 0; i < nodeCount; i++) { broadcasters[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)).Wait(); await Task.Delay(TimeSpan.FromSeconds(1)); } ((Client.IConnection)connection).Disconnect(); await Task.Delay(TimeSpan.FromTicks(TimeSpan.FromSeconds(5).Ticks * nodeCount)); Assert.Equal(0, disconnectCounter.CleanDisconnectCount); Assert.Equal(3, disconnectCounter.UncleanDisconnectCount); } }
public void GroupsAreNotReadOnConnectedAsyncLongPolling() { var host = new MemoryHost(); host.MapConnection<MyConnection>("/echo"); var connection = new Client.Connection("http://foo/echo"); connection.Groups = new List<string> { typeof(MyConnection).FullName + ".test" }; connection.Received += data => { Assert.False(true, "Unexpectedly received data"); }; var transport = new Client.Transports.LongPollingTransport(host); connection.Start(transport).Wait(); Thread.Sleep(TimeSpan.FromSeconds(10)); }
public void FarmDisconnectOnlyRaisesEventOnce() { // Each node shares the same bus but are indepenent servers var counters = new SignalR.Infrastructure.PerformanceCounterManager(); var bus = new MessageBus(new TraceManager(), counters); var nodeCount = 3; var nodes = new List <ServerNode>(); for (int i = 0; i < nodeCount; i++) { nodes.Add(new ServerNode(bus)); } var timeout = TimeSpan.FromSeconds(5); foreach (var node in nodes) { node.Server.Configuration.HeartBeatInterval = timeout; node.Server.Configuration.DisconnectTimeout = TimeSpan.Zero; node.Server.MapConnection <FarmConnection>("/echo"); } var loadBalancer = new LoadBalancer(nodes.Select(f => f.Server).ToArray()); var transport = new Client.Transports.LongPollingTransport(loadBalancer); var connection = new Client.Connection("http://goo/echo"); connection.Start(transport).Wait(); for (int i = 0; i < nodes.Count; i++) { nodes[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)); Thread.Sleep(TimeSpan.FromSeconds(1)); } connection.Stop(); Thread.Sleep(TimeSpan.FromTicks(timeout.Ticks * nodes.Count)); Assert.Equal(1, nodes.Sum(n => n.Connection.DisconnectCount)); }
public void GroupsAreNotReadOnConnectedAsyncLongPolling() { using (var host = new MemoryHost()) { host.MapConnection <MyConnection>("/echo"); var connection = new Client.Connection("http://foo/echo"); connection.Groups = new List <string> { typeof(MyConnection).FullName + ".test" }; connection.Received += data => { Assert.False(true, "Unexpectedly received data"); }; var transport = new Client.Transports.LongPollingTransport(host); connection.Start(transport).Wait(); Thread.Sleep(TimeSpan.FromSeconds(5)); connection.Stop(); } }
public async Task FarmDisconnectRaisesUncleanDisconnects() { // Each node shares the same bus but are independent servers const int nodeCount = 3; var counters = new PerformanceCounterManager(); var configurationManager = new DefaultConfigurationManager(); configurationManager.DisconnectTimeout = TimeSpan.FromSeconds(6); using (EnableTracing()) using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000)) using (var loadBalancer = new LoadBalancer(nodeCount)) { var broadcasters = new List <IConnection>(); var disconnectCounter = Channel.CreateUnbounded <DisconnectData>(); loadBalancer.Configure(app => { var resolver = new DefaultDependencyResolver(); resolver.Register(typeof(IMessageBus), () => bus); resolver.Register(typeof(IConfigurationManager), () => configurationManager); resolver.Register(typeof(FarmConnection), () => new FarmConnection(disconnectCounter.Writer)); var connectionManager = resolver.Resolve <IConnectionManager>(); broadcasters.Add(connectionManager.GetConnectionContext <FarmConnection>().Connection); app.MapSignalR <FarmConnection>("/echo", new ConnectionConfiguration { Resolver = resolver }); }); var transport = new Client.Transports.LongPollingTransport(loadBalancer); var connection = new Client.Connection("http://goo/echo"); await connection.Start(transport); for (int i = 0; i < nodeCount; i++) { broadcasters[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)).Wait(); await Task.Delay(TimeSpan.FromSeconds(1)); } ((Client.IConnection)connection).Disconnect(); // Give up after 30 seconds var cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(30)); // We can get duplicate OnDisconnected calls, and that's a known by-design issue. var instancesDisconnected = new HashSet <string>(); while (await disconnectCounter.Reader.WaitToReadAsync(cts.Token)) { while (!cts.IsCancellationRequested && disconnectCounter.Reader.TryRead(out var disconnect)) { Assert.False(disconnect.StopCalled, "Disconnect should not have been due to stop being called."); instancesDisconnected.Add(disconnect.InstanceName); if (instancesDisconnected.Count == 3) { // We're done, all three instances disconneted return; } } } // If we get here it means the cts was cancelled which means we timed out cts.Token.ThrowIfCancellationRequested(); } }
public async Task FarmGroupAddCompletesSuccessfully(TransportType transportType) { // https://github.com/SignalR/SignalR/issues/3337 // Each node shares the same bus but are independent servers const int nodeCount = 2; var counters = new PerformanceCounterManager(); var configurationManager = new DefaultConfigurationManager(); // Ensure /send and /connect requests get handled by different servers Func <string, int> scheduler = url => url.Contains("/send") ? 0 : 1; using (EnableTracing()) using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000)) using (var loadBalancer = new LoadBalancer(nodeCount, scheduler)) { loadBalancer.Configure(app => { var resolver = new DefaultDependencyResolver(); resolver.Register(typeof(IMessageBus), () => bus); app.MapSignalR(new HubConfiguration { Resolver = resolver }); }); using (var connection = new HubConnection("http://goo/")) { var proxy = connection.CreateHubProxy("FarmGroupHub"); const string group = "group"; const string message = "message"; var mre = new AsyncManualResetEvent(); proxy.On <string>("message", m => { if (m == message) { mre.Set(); } }); Client.Transports.IClientTransport transport; switch (transportType) { case TransportType.LongPolling: transport = new Client.Transports.LongPollingTransport(loadBalancer); break; case TransportType.ServerSentEvents: transport = new Client.Transports.ServerSentEventsTransport(loadBalancer); break; default: throw new ArgumentException("transportType"); } await connection.Start(transport); await proxy.Invoke("JoinGroup", group); await proxy.Invoke("SendToGroup", group, message); Assert.True(await mre.WaitAsync(TimeSpan.FromSeconds(5))); } } }
public void FarmDisconnectOnlyRaisesEventOnce() { // Each node shares the same bus but are indepenent servers var bus = new InProcessMessageBus(new TraceManager(), garbageCollectMessages: false); var nodeCount = 3; var nodes = new List<ServerNode>(); for (int i = 0; i < nodeCount; i++) { nodes.Add(new ServerNode(bus)); } var timeout = TimeSpan.FromSeconds(5); foreach (var node in nodes) { node.Server.Configuration.HeartBeatInterval = timeout; node.Server.Configuration.DisconnectTimeout = TimeSpan.Zero; node.Server.MapConnection<FarmConnection>("/echo"); } var loadBalancer = new LoadBalancer(nodes.Select(f => f.Server).ToArray()); var transport = new Client.Transports.LongPollingTransport(loadBalancer); var connection = new Client.Connection("http://goo/echo"); connection.Start(transport).Wait(); for (int i = 0; i < nodes.Count; i++) { nodes[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)); Thread.Sleep(TimeSpan.FromSeconds(1)); } Thread.Sleep(TimeSpan.FromTicks(timeout.Ticks * nodes.Count)); Assert.Equal(1, nodes.Sum(n => n.Connection.DisconnectCount)); }
public async Task FarmGroupAddCompletesSuccessfully(TransportType transportType) { // https://github.com/SignalR/SignalR/issues/3337 // Each node shares the same bus but are independent servers const int nodeCount = 2; var counters = new Infrastructure.PerformanceCounterManager(); var configurationManager = new DefaultConfigurationManager(); // Ensure /send and /connect requests get handled by different servers Func<string, int> scheduler = url => url.Contains("/send") ? 0 : 1; using (EnableDisposableTracing()) using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000)) using (var loadBalancer = new LoadBalancer(nodeCount, scheduler)) { loadBalancer.Configure(app => { var resolver = new DefaultDependencyResolver(); resolver.Register(typeof(IMessageBus), () => bus); app.MapSignalR(new HubConfiguration { Resolver = resolver }); }); using (var connection = new HubConnection("http://goo/")) { var proxy = connection.CreateHubProxy("FarmGroupHub"); const string group = "group"; const string message = "message"; var mre = new AsyncManualResetEvent(); proxy.On<string>("message", m => { if (m == message) { mre.Set(); } }); Client.Transports.IClientTransport transport; switch (transportType) { case TransportType.LongPolling: transport = new Client.Transports.LongPollingTransport(loadBalancer); break; case TransportType.ServerSentEvents: transport = new Client.Transports.ServerSentEventsTransport(loadBalancer); break; default: throw new ArgumentException("transportType"); } await connection.Start(transport); await proxy.Invoke("JoinGroup", group); await proxy.Invoke("SendToGroup", group, message); Assert.True(await mre.WaitAsync(TimeSpan.FromSeconds(5))); } } }
public async Task FarmDisconnectOnlyRaisesUncleanDisconnects() { EnableTracing(); // Each node shares the same bus but are indepenent servers var counters = new SignalR.Infrastructure.PerformanceCounterManager(); var configurationManager = new DefaultConfigurationManager(); var protectedData = new DefaultProtectedData(); using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000)) { var nodeCount = 3; var nodes = new List<ServerNode>(); for (int i = 0; i < nodeCount; i++) { nodes.Add(new ServerNode(bus)); } var timeout = TimeSpan.FromSeconds(5); foreach (var node in nodes) { var config = node.Resolver.Resolve<IConfigurationManager>(); config.DisconnectTimeout = TimeSpan.FromSeconds(6); IDependencyResolver resolver = node.Resolver; node.Server.Configure(app => { app.MapSignalR<FarmConnection>("/echo", new ConnectionConfiguration { Resolver = resolver }); resolver.Register(typeof(IProtectedData), () => protectedData); }); } var loadBalancer = new LoadBalancer(nodes.Select(f => f.Server).ToArray()); var transport = new Client.Transports.LongPollingTransport(loadBalancer); var connection = new Client.Connection("http://goo/echo"); await connection.Start(transport); for (int i = 0; i < nodes.Count; i++) { nodes[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)); await Task.Delay(TimeSpan.FromSeconds(1)); } ((Client.IConnection)connection).Disconnect(); await Task.Delay(TimeSpan.FromTicks(timeout.Ticks * nodes.Count)); Assert.Equal(0, FarmConnection.OldOnDisconnectedCalls); Assert.Equal(0, FarmConnection.CleanDisconnectCount); Assert.Equal(3, FarmConnection.UncleanDisconnectCount); } }
public void FarmDisconnectOnlyRaisesEventOnce() { // Each node shares the same bus but are indepenent servers var counters = new SignalR.Infrastructure.PerformanceCounterManager(); var configurationManager = new DefaultConfigurationManager(); using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000)) { var nodeCount = 3; var nodes = new List<ServerNode>(); for (int i = 0; i < nodeCount; i++) { nodes.Add(new ServerNode(bus)); } var timeout = TimeSpan.FromSeconds(5); foreach (var node in nodes) { var config = node.Resolver.Resolve<IConfigurationManager>(); config.DisconnectTimeout = TimeSpan.FromSeconds(6); IDependencyResolver resolver = node.Resolver; node.Server.Configure(app => { app.MapConnection<FarmConnection>("/echo", new ConnectionConfiguration { Resolver = resolver }); }); } var loadBalancer = new LoadBalancer(nodes.Select(f => f.Server).ToArray()); var transport = new Client.Transports.LongPollingTransport(loadBalancer); var connection = new Client.Connection("http://goo/echo"); connection.Start(transport).Wait(); for (int i = 0; i < nodes.Count; i++) { nodes[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)); Thread.Sleep(TimeSpan.FromSeconds(1)); } connection.Disconnect(); Thread.Sleep(TimeSpan.FromTicks(timeout.Ticks * nodes.Count)); Assert.Equal(1, nodes.Sum(n => n.Connection.DisconnectCount)); } }