diff --git a/src/ServiceStack.Redis/RedisNativeClient.cs b/src/ServiceStack.Redis/RedisNativeClient.cs index 939847be..a34ec81d 100644 --- a/src/ServiceStack.Redis/RedisNativeClient.cs +++ b/src/ServiceStack.Redis/RedisNativeClient.cs @@ -111,7 +111,7 @@ internal IRedisPipelineShared Pipeline } public RedisNativeClient(string host) - : this(host, DefaultPort) {} + : this(host.SplitOnLast(':')[0], host.Contains(':') ? int.Parse(host.SplitOnLast(':')[1]) : DefaultPort) { } public RedisNativeClient(string host, int port) : this(host, port, null) {} diff --git a/src/TestMqHost/Program2.cs b/src/TestMqHost/Program2.cs index 7181a72c..44c5adda 100644 --- a/src/TestMqHost/Program2.cs +++ b/src/TestMqHost/Program2.cs @@ -13,13 +13,17 @@ namespace TestMqHost { class Program2 { + static void Main(string[] args) { var clientManager = new PooledRedisClientManager(new[] { "localhost" }) { PoolTimeout = 1000, }; - clientManager.GetClient().FlushAll(); + using (var client = clientManager.GetClient()) + { + client.FlushAll(); + } var mqHost = new RedisMqServer(clientManager); diff --git a/tests/ServiceStack.Redis.Tests/RedisFailoverTests.cs b/tests/ServiceStack.Redis.Tests/RedisFailoverTests.cs index b5d242f7..3b3298c3 100644 --- a/tests/ServiceStack.Redis.Tests/RedisFailoverTests.cs +++ b/tests/ServiceStack.Redis.Tests/RedisFailoverTests.cs @@ -140,5 +140,78 @@ public void Can_MqServer_recover_from_server_terminated_client_connections() }); } + + [Test] + public void Can_failover_at_runtime() + { + var failoverHost = "ny-devredis01:6380"; + var localClient = new RedisClient("localhost"); + string key = "test:failover"; + + localClient.Remove(key); + var failoverClient = new RedisClient(failoverHost); + failoverClient.Remove(key); + + var clientManager = new PooledRedisClientManager(new[] { "localhost" }); + + RunInLoop(clientManager, callback:() => + { + lock (clientManager) + Monitor.Pulse(clientManager); + }); + + Thread.Sleep(100); + + clientManager.FailoverTo(failoverHost); + + lock (clientManager) + Monitor.Wait(clientManager); + + var localIncr = localClient.Get(key); + var failoverIncr = failoverClient.Get(key); + Assert.That(localIncr, Is.GreaterThan(0)); + Assert.That(failoverIncr, Is.GreaterThan(0)); + Assert.That(localIncr + failoverIncr, Is.EqualTo(100)); + } + + + public static bool RunInLoop(PooledRedisClientManager clientManager, int iterations = 100, int sleepMs = 10, Action callback=null) + { + int count = 0; + int errors = 0; + + 10.Times(i => + { + ThreadPool.QueueUserWorkItem(_ => + { + while (iterations-- > 0) + { + using (var client = clientManager.GetClient()) + { + try + { + var result = client.Increment("test:failover", 1); + if (++count % (iterations / 10) == 0) + lock (clientManager) + Console.WriteLine("count: {0}, errors: {1}", count, errors); + } + catch (Exception ex) + { + errors++; + } + Thread.Sleep(sleepMs); + } + } + + if (callback != null) + { + callback(); + callback = null; + } + }); + }); + + return true; + } } } \ No newline at end of file