public async Task WritingToGroupWithOneConnectionFailingSecondConnectionStillReceivesMessage()
        {
            var manager = new RedisHubLifetimeManager<MyHub>(new LoggerFactory().CreateLogger<RedisHubLifetimeManager<MyHub>>(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client1 = new TestClient())
            using (var client2 = new TestClient())
            {
                // Force an exception when writing to connection
                var writer = new Mock<ChannelWriter<HubMessage>>();
                writer.Setup(o => o.WaitToWriteAsync(It.IsAny<CancellationToken>())).Throws(new Exception());

                var connection1 = HubConnectionContextUtils.Create(client1.Connection, new MockChannel(writer.Object));
                var connection2 = HubConnectionContextUtils.Create(client2.Connection);

                await manager.OnConnectedAsync(connection1).OrTimeout();
                await manager.AddGroupAsync(connection1.ConnectionId, "group");
                await manager.OnConnectedAsync(connection2).OrTimeout();
                await manager.AddGroupAsync(connection2.ConnectionId, "group");

                await manager.InvokeGroupAsync("group", "Hello", new object[] { "World" }).OrTimeout();
                // connection1 will throw when receiving a group message, we are making sure other connections
                // are not affected by another connection throwing
                await AssertMessageAsync(client2);

                // Repeat to check that group can still be sent to
                await manager.InvokeGroupAsync("group", "Hello", new object[] { "World" }).OrTimeout();
                await AssertMessageAsync(client2);
            }
        }
        public async Task InvokeConnectionAsyncForLocalConnectionDoesNotPublishToRedis()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var output = Channel.CreateUnbounded <HubMessage>();

                var connection = new HubConnectionContext(output, client.Connection);

                // Add connection to both "servers" to see if connection receives message twice
                await manager1.OnConnectedAsync(connection).OrTimeout();

                await manager2.OnConnectedAsync(connection).OrTimeout();

                await manager1.InvokeConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout();

                AssertMessage(output);
                Assert.False(output.In.TryRead(out var item));
            }
        }
예제 #3
0
        // Re-enable micro-benchmark when https://github.com/aspnet/SignalR/issues/3088 is fixed
        // [GlobalSetup]
        public void GlobalSetup()
        {
            var server    = new TestRedisServer();
            var logger    = NullLogger <RedisHubLifetimeManager <TestHub> > .Instance;
            var protocols = GenerateProtocols(ProtocolCount).ToArray();
            var options   = Options.Create(new RedisOptions()
            {
                ConnectionFactory = _ => Task.FromResult <IConnectionMultiplexer>(new TestConnectionMultiplexer(server))
            });
            var resolver = new DefaultHubProtocolResolver(protocols, NullLogger <DefaultHubProtocolResolver> .Instance);

            _manager1 = new RedisHubLifetimeManager <TestHub>(logger, options, resolver);
            _manager2 = new RedisHubLifetimeManager <TestHub>(logger, options, resolver);

            async Task ConnectClient(TestClient client, IHubProtocol protocol, string userId, string groupName)
            {
                await _manager2.OnConnectedAsync(HubConnectionContextUtils.Create(client.Connection, protocol, userId));

                await _manager2.AddToGroupAsync(client.Connection.ConnectionId, "Everyone");

                await _manager2.AddToGroupAsync(client.Connection.ConnectionId, groupName);
            }

            // Connect clients
            _clients = new TestClient[ClientCount];
            var tasks = new Task[ClientCount];

            for (var i = 0; i < _clients.Length; i++)
            {
                var protocol = protocols[i % ProtocolCount];
                _clients[i] = new TestClient(protocol: protocol);

                string group;
                string user;
                if ((i % 2) == 0)
                {
                    group = "Evens";
                    user  = "******";
                    _excludedConnectionIds.Add(_clients[i].Connection.ConnectionId);
                }
                else
                {
                    group = "Odds";
                    user  = "******";
                    _sendIds.Add(_clients[i].Connection.ConnectionId);
                }

                tasks[i] = ConnectClient(_clients[i], protocol, user, group);
                _        = ConsumeAsync(_clients[i]);
            }

            Task.WaitAll(tasks);

            _groups.Add("Evens");
            _groups.Add("Odds");
            _users.Add("EvenUser");
            _users.Add("OddUser");

            _args = new object[] { "Foo" };
        }
예제 #4
0
        public async Task InvokeAllAsyncDoesNotWriteToDisconnectedConnectionsOutput()
        {
            using (var client1 = new TestClient())
                using (var client2 = new TestClient())
                {
                    var manager = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                                      Options.Create(new RedisOptions()
                    {
                        Factory = t => new TestConnectionMultiplexer()
                    }));
                    var connection1 = HubConnectionContextUtils.Create(client1.Connection);
                    var connection2 = HubConnectionContextUtils.Create(client2.Connection);

                    await manager.OnConnectedAsync(connection1).OrTimeout();

                    await manager.OnConnectedAsync(connection2).OrTimeout();

                    await manager.OnDisconnectedAsync(connection2).OrTimeout();

                    await manager.SendAllAsync("Hello", new object[] { "World" }).OrTimeout();

                    await AssertMessageAsync(client1);

                    Assert.Null(client2.TryRead());
                }
        }
        public async Task InvokeGroupAsyncWritesToAllConnectionsInGroupOutput()
        {
            using (var client1 = new TestClient())
                using (var client2 = new TestClient())
                {
                    var output1 = Channel.CreateUnbounded <HubMessage>();
                    var output2 = Channel.CreateUnbounded <HubMessage>();

                    var manager = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                                      Options.Create(new RedisOptions()
                    {
                        Factory = t => new TestConnectionMultiplexer()
                    }));
                    var connection1 = new HubConnectionContext(output1, client1.Connection);
                    var connection2 = new HubConnectionContext(output2, client2.Connection);

                    await manager.OnConnectedAsync(connection1).OrTimeout();

                    await manager.OnConnectedAsync(connection2).OrTimeout();

                    await manager.AddGroupAsync(connection1.ConnectionId, "gunit").OrTimeout();

                    await manager.InvokeGroupAsync("gunit", "Hello", new object[] { "World" }).OrTimeout();

                    AssertMessage(output1);

                    Assert.False(output2.In.TryRead(out var item));
                }
        }
예제 #6
0
        public async Task DisconnectConnectionRemovesConnectionFromGroup()
        {
            var manager = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                              Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var connection = HubConnectionContextUtils.Create(client.Connection);

                await manager.OnConnectedAsync(connection).OrTimeout();

                await manager.AddGroupAsync(connection.ConnectionId, "name").OrTimeout();

                await manager.OnDisconnectedAsync(connection).OrTimeout();

                await manager.SendGroupAsync("name", "Hello", new object[] { "World" }).OrTimeout();

                await connection.DisposeAsync().OrTimeout();

                Assert.Null(client.TryRead());
            }
        }
예제 #7
0
        public async Task WritingToRemoteConnectionThatFailsDoesNotThrow()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                // Force an exception when writing to connection
                var writer = new Mock <ChannelWriter <HubMessage> >();
                writer.Setup(o => o.WaitToWriteAsync(It.IsAny <CancellationToken>())).Throws(new Exception());

                var connection = HubConnectionContextUtils.Create(client.Connection, new MockChannel(writer.Object));

                await manager2.OnConnectedAsync(connection).OrTimeout();

                // This doesn't throw because there is no connection.ConnectionId on this server so it has to publish to redis.
                // And once that happens there is no way to know if the invocation was successful or not.
                await manager1.InvokeConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout();
            }
        }
예제 #8
0
        public async Task InvokeGroupAsyncWritesToAllConnectionsInGroupOutput()
        {
            using (var client1 = new TestClient())
                using (var client2 = new TestClient())
                {
                    var manager = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                                      Options.Create(new RedisOptions()
                    {
                        Factory = t => new TestConnectionMultiplexer()
                    }));
                    var connection1 = HubConnectionContextUtils.Create(client1.Connection);
                    var connection2 = HubConnectionContextUtils.Create(client2.Connection);

                    await manager.OnConnectedAsync(connection1).OrTimeout();

                    await manager.OnConnectedAsync(connection2).OrTimeout();

                    await manager.AddGroupAsync(connection1.ConnectionId, "gunit").OrTimeout();

                    await manager.InvokeGroupAsync("gunit", "Hello", new object[] { "World" }).OrTimeout();

                    await AssertMessageAsync(client1);

                    await connection1.DisposeAsync().OrTimeout();

                    await connection2.DisposeAsync().OrTimeout();

                    Assert.Null(client2.TryRead());
                }
        }
예제 #9
0
        public async Task RemoveGroupAsyncForConnectionOnDifferentServerWorks()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var connection = HubConnectionContextUtils.Create(client.Connection);

                await manager1.OnConnectedAsync(connection).OrTimeout();

                await manager1.AddGroupAsync(connection.ConnectionId, "name").OrTimeout();

                await manager2.InvokeGroupAsync("name", "Hello", new object[] { "World" }).OrTimeout();

                await AssertMessageAsync(client);

                await manager2.RemoveGroupAsync(connection.ConnectionId, "name").OrTimeout();

                await manager2.InvokeGroupAsync("name", "Hello", new object[] { "World" }).OrTimeout();

                await connection.DisposeAsync().OrTimeout();

                Assert.Null(client.TryRead());
            }
        }
예제 #10
0
        public async Task InvokeConnectionAsyncForLocalConnectionDoesNotPublishToRedis()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var connection = HubConnectionContextUtils.Create(client.Connection);

                // Add connection to both "servers" to see if connection receives message twice
                await manager1.OnConnectedAsync(connection).OrTimeout();

                await manager2.OnConnectedAsync(connection).OrTimeout();

                await manager1.InvokeConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout();

                await connection.DisposeAsync().OrTimeout();

                await AssertMessageAsync(client);

                Assert.Null(client.TryRead());
            }
        }
예제 #11
0
        public async Task InvokeGroupAsyncOnServerWithoutConnectionWritesOutputToGroupConnection()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var connection = HubConnectionContextUtils.Create(client.Connection);

                await manager1.OnConnectedAsync(connection).OrTimeout();

                await manager1.AddGroupAsync(connection.ConnectionId, "name").OrTimeout();

                await manager2.InvokeGroupAsync("name", "Hello", new object[] { "World" }).OrTimeout();

                await AssertMessageAsync(client);
            }
        }
        public async Task RemoveGroupAsyncForConnectionOnDifferentServerWorks()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var output = Channel.CreateUnbounded <HubMessage>();

                var connection = new HubConnectionContext(output, client.Connection);

                await manager1.OnConnectedAsync(connection).OrTimeout();

                await manager1.AddGroupAsync(connection.ConnectionId, "name").OrTimeout();

                await manager2.InvokeGroupAsync("name", "Hello", new object[] { "World" }).OrTimeout();

                AssertMessage(output);

                await manager2.RemoveGroupAsync(connection.ConnectionId, "name").OrTimeout();

                await manager2.InvokeGroupAsync("name", "Hello", new object[] { "World" }).OrTimeout();

                Assert.False(output.In.TryRead(out var item));
            }
        }
예제 #13
0
        public async Task InvokeAllAsyncWithMultipleServersWritesToAllConnectionsOutput()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client1 = new TestClient())
                using (var client2 = new TestClient())
                {
                    var connection1 = HubConnectionContextUtils.Create(client1.Connection);
                    var connection2 = HubConnectionContextUtils.Create(client2.Connection);

                    await manager1.OnConnectedAsync(connection1).OrTimeout();

                    await manager2.OnConnectedAsync(connection2).OrTimeout();

                    await manager1.InvokeAllAsync("Hello", new object[] { "World" }).OrTimeout();

                    await AssertMessageAsync(client1);
                    await AssertMessageAsync(client2);
                }
        }
예제 #14
0
        public async Task AddGroupAsyncForLocalConnectionAlreadyInGroupDoesNothing()
        {
            var manager = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var connection = HubConnectionContextUtils.Create(client.Connection);

                await manager.OnConnectedAsync(connection).OrTimeout();

                await manager.AddGroupAsync(connection.ConnectionId, "name").OrTimeout();

                await manager.AddGroupAsync(connection.ConnectionId, "name").OrTimeout();

                await manager.SendGroupAsync("name", "Hello", new object[] { "World" }).OrTimeout();


                await AssertMessageAsync(client);

                Assert.Null(client.TryRead());
            }
        }
        public async Task InvokeConnectionAsyncOnServerWithoutConnectionWritesOutputToConnection()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var output = Channel.CreateUnbounded <HubMessage>();

                var connection = new HubConnectionContext(output, client.Connection);

                await manager1.OnConnectedAsync(connection).OrTimeout();

                await manager2.InvokeConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout();

                AssertMessage(output);
            }
        }
        public async Task InvokeAllAsyncWithMultipleServersDoesNotWriteToDisconnectedConnectionsOutput()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client1 = new TestClient())
                using (var client2 = new TestClient())
                {
                    var output1 = Channel.CreateUnbounded <HubMessage>();
                    var output2 = Channel.CreateUnbounded <HubMessage>();

                    var connection1 = new HubConnectionContext(output1, client1.Connection);
                    var connection2 = new HubConnectionContext(output2, client2.Connection);

                    await manager1.OnConnectedAsync(connection1).OrTimeout();

                    await manager2.OnConnectedAsync(connection2).OrTimeout();

                    await manager2.OnDisconnectedAsync(connection2).OrTimeout();

                    await manager2.InvokeAllAsync("Hello", new object[] { "World" }).OrTimeout();

                    AssertMessage(output1);

                    Assert.False(output2.In.TryRead(out var item));
                }
        }
예제 #17
0
 public async Task InvokeConnectionAsyncOnNonExistentConnectionDoesNotThrow()
 {
     var manager = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                       Options.Create(new RedisOptions()
     {
         Factory = t => new TestConnectionMultiplexer()
     }));
     await manager.InvokeConnectionAsync("NotARealConnectionId", "Hello", new object[] { "World" }).OrTimeout();
 }
예제 #18
0
        public async Task RemoveGroupFromLocalConnectionNotInGroupDoesNothing()
        {
            var manager = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                              Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var connection = HubConnectionContextUtils.Create(client.Connection);

                await manager.OnConnectedAsync(connection).OrTimeout();

                await manager.RemoveGroupAsync(connection.ConnectionId, "name").OrTimeout();
            }
        }
예제 #19
0
        public async Task InvokeConnectionAsyncWritesToConnectionOutput()
        {
            using (var client = new TestClient())
            {
                var manager = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                                  Options.Create(new RedisOptions()
                {
                    Factory = t => new TestConnectionMultiplexer()
                }));
                var connection = HubConnectionContextUtils.Create(client.Connection);

                await manager.OnConnectedAsync(connection).OrTimeout();

                await manager.SendConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout();

                await AssertMessageAsync(client);
            }
        }
예제 #20
0
        public async Task WritingToLocalConnectionThatFailsDoesNotThrowException()
        {
            var manager = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                // Force an exception when writing to connection
                var connectionMock = HubConnectionContextUtils.CreateMock(client.Connection);
                connectionMock.Setup(m => m.WriteAsync(It.IsAny <HubMessage>())).Throws(new Exception("Message"));
                var connection = connectionMock.Object;

                await manager.OnConnectedAsync(connection).OrTimeout();

                await manager.SendConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout();
            }
        }
        public async Task WritingToLocalConnectionThatFailsThrowsException()
        {
            var manager = new RedisHubLifetimeManager<MyHub>(new LoggerFactory().CreateLogger<RedisHubLifetimeManager<MyHub>>(), Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                // Force an exception when writing to connection
                var writer = new Mock<ChannelWriter<HubMessage>>();
                writer.Setup(o => o.WaitToWriteAsync(It.IsAny<CancellationToken>())).Throws(new Exception("Message"));

                var connection = HubConnectionContextUtils.Create(client.Connection, new MockChannel(writer.Object));

                await manager.OnConnectedAsync(connection).OrTimeout();

                var exception = await Assert.ThrowsAsync<Exception>(() => manager.InvokeConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout());
                Assert.Equal("Message", exception.Message);
            }
        }
        public async Task RemoveGroupFromConnectionOnDifferentServerNotInGroupDoesNothing()
        {
            var manager1 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));
            var manager2 = new RedisHubLifetimeManager <MyHub>(new LoggerFactory().CreateLogger <RedisHubLifetimeManager <MyHub> >(),
                                                               Options.Create(new RedisOptions()
            {
                Factory = t => new TestConnectionMultiplexer()
            }));

            using (var client = new TestClient())
            {
                var output = Channel.CreateUnbounded <HubMessage>();

                var connection = new HubConnectionContext(output, client.Connection);

                await manager1.OnConnectedAsync(connection).OrTimeout();

                await manager2.RemoveGroupAsync(connection.ConnectionId, "name").OrTimeout();
            }
        }