예제 #1
0
        public async Task PrimaryReplicaSubscriptionFailover(CommandFlags flags, bool expectSuccess)
        {
            var config = TestConfig.Current.PrimaryServerAndPort + "," + TestConfig.Current.ReplicaServerAndPort;

            Log("Connecting...");
            using var muxer = (Create(configuration: config, shared: false, allowAdmin: true) as ConnectionMultiplexer) !;
            var sub     = muxer.GetSubscriber();
            var channel = (RedisChannel)(Me() + flags.ToString()); // Individual channel per case to not overlap publishers

            var count = 0;

            Log("Subscribing...");
            await sub.SubscribeAsync(channel, (_, val) =>
            {
                Interlocked.Increment(ref count);
                Log("Message: " + val);
            }, flags);

            Assert.True(sub.IsConnected(channel));

            Log("Publishing (1)...");
            Assert.Equal(0, count);
            var publishedTo = await sub.PublishAsync(channel, "message1");

            // Client -> Redis -> Client -> handler takes just a moment
            await UntilConditionAsync(TimeSpan.FromSeconds(2), () => Volatile.Read(ref count) == 1);

            Assert.Equal(1, count);
            Log($"  Published (1) to {publishedTo} subscriber(s).");

            var endpoint                 = sub.SubscribedEndpoint(channel);
            var subscribedServer         = muxer.GetServer(endpoint);
            var subscribedServerEndpoint = muxer.GetServerEndPoint(endpoint);

            Assert.True(subscribedServer.IsConnected, "subscribedServer.IsConnected");
            Assert.True(subscribedServerEndpoint.IsConnected, "subscribedServerEndpoint.IsConnected");
            Assert.True(subscribedServerEndpoint.IsSubscriberConnected, "subscribedServerEndpoint.IsSubscriberConnected");

            Assert.True(muxer.TryGetSubscription(channel, out var subscription));
            var initialServer = subscription.GetCurrentServer();

            Assert.NotNull(initialServer);
            Assert.True(initialServer.IsConnected);
            Log("Connected to: " + initialServer);

            muxer.AllowConnect = false;
            subscribedServerEndpoint.SimulateConnectionFailure(SimulatedFailureType.AllSubscription);

            Assert.True(subscribedServerEndpoint.IsConnected, "subscribedServerEndpoint.IsConnected");
            Assert.False(subscribedServerEndpoint.IsSubscriberConnected, "subscribedServerEndpoint.IsSubscriberConnected");

            if (expectSuccess)
            {
                await UntilConditionAsync(TimeSpan.FromSeconds(5), () => subscription.IsConnected);

                Assert.True(subscription.IsConnected);

                var newServer = subscription.GetCurrentServer();
                Assert.NotNull(newServer);
                Assert.NotEqual(newServer, initialServer);
                Log("Now connected to: " + newServer);
            }
            else
            {
                // This subscription shouldn't be able to reconnect by flags (demanding an unavailable server)
                await UntilConditionAsync(TimeSpan.FromSeconds(5), () => subscription.IsConnected);

                Assert.False(subscription.IsConnected);
                Log("Unable to reconnect (as expected)");

                // Allow connecting back to the original
                muxer.AllowConnect = true;
                await UntilConditionAsync(TimeSpan.FromSeconds(5), () => subscription.IsConnected);

                Assert.True(subscription.IsConnected);

                var newServer = subscription.GetCurrentServer();
                Assert.NotNull(newServer);
                Assert.Equal(newServer, initialServer);
                Log("Now connected to: " + newServer);
            }

            count = 0;
            Log("Publishing (2)...");
            Assert.Equal(0, count);
            publishedTo = await sub.PublishAsync(channel, "message2");

            // Client -> Redis -> Client -> handler takes just a moment
            await UntilConditionAsync(TimeSpan.FromSeconds(2), () => Volatile.Read(ref count) == 1);

            Assert.Equal(1, count);
            Log($"  Published (2) to {publishedTo} subscriber(s).");

            ClearAmbientFailures();
        }
 [InlineData(CommandFlags.DemandReplica | CommandFlags.FireAndForget, "PreferMaster, FireAndForget, DemandReplica")] // 2-bit flag is hit-and-miss
 public void CommandFlagsFormatting(CommandFlags value, string expected)
 => Assert.Equal(expected, value.ToString());