public async Task ReadOnlyConnectionSlavesTest() { var slaves = SentinelServerA.SentinelSlaves(ServiceName); var config = new ConfigurationOptions { TieBreaker = "", ServiceName = TestConfig.Current.SentinelSeviceName, }; foreach (var kv in slaves) { Assert.Equal("slave", kv.ToDictionary()["flags"]); config.EndPoints.Add(kv.ToDictionary()["name"]); } var readonlyConn = ConnectionMultiplexer.Connect(config); await UntilCondition(TimeSpan.FromSeconds(2), () => readonlyConn.IsConnected); Assert.True(readonlyConn.IsConnected); var db = readonlyConn.GetDatabase(); var s = db.StringGet("test"); Assert.True(s.IsNullOrEmpty); //var ex = Assert.Throws<RedisConnectionException>(() => db.StringSet("test", "try write to read only instance")); //Assert.StartsWith("No connection is available to service this operation", ex.Message); }
public void SentinelSlavesTest() { var slaveConfigs = SentinelServerA.SentinelSlaves(ServiceName); Assert.True(slaveConfigs.Length > 0); Assert.True(slaveConfigs[0].ToDictionary().ContainsKey("name")); Assert.StartsWith("slave", slaveConfigs[0].ToDictionary()["flags"]); foreach (var config in slaveConfigs) { foreach (var kvp in config) { Log("{0}:{1}", kvp.Key, kvp.Value); } } }
public async Task GetSentinelMasterConnectionWriteReadFailover() { Log("Conn:"); foreach (var server in Conn.GetServerSnapshot().ToArray()) { Log(" Endpoint: " + server.EndPoint); } Log("Conn Slaves:"); foreach (var slaves in SentinelServerA.SentinelSlaves(ServiceName)) { foreach (var pair in slaves) { Log(" {0}: {1}", pair.Key, pair.Value); } } var conn = Conn.GetSentinelMasterConnection(ServiceOptions); var s = conn.currentSentinelMasterEndPoint.ToString(); Log("Sentinel Master Endpoint: " + s); foreach (var server in conn.GetServerSnapshot().ToArray()) { Log(" Server: " + server.EndPoint); Log(" Master Endpoint: " + server.MasterEndPoint); Log(" IsSlave: " + server.IsSlave); Log(" SlaveReadOnly: " + server.SlaveReadOnly); var info = conn.GetServer(server.EndPoint).Info("Replication"); foreach (var section in info) { Log(" Section: " + section.Key); foreach (var pair in section) { Log(" " + pair.Key + ": " + pair.Value); } } } IDatabase db = conn.GetDatabase(); var expected = DateTime.Now.Ticks.ToString(); Log("Tick Key: " + expected); var key = Me(); db.KeyDelete(key, CommandFlags.FireAndForget); db.StringSet(key, expected); await UntilCondition(TimeSpan.FromSeconds(10), () => SentinelServerA.SentinelMaster(ServiceName).ToDictionary()["num-slaves"] != "0" ); Log("Conditions met"); try { Log("Failover attempted initiated"); SentinelServerA.SentinelFailover(ServiceName); Log(" Success!"); } catch (RedisServerException ex) when(ex.Message.Contains("NOGOODSLAVE")) { // Retry once Log(" Retry initiated"); await Task.Delay(1000).ForAwait(); SentinelServerA.SentinelFailover(ServiceName); Log(" Retry complete"); } Log("Delaying for failover conditions..."); await Task.Delay(2000).ForAwait(); Log("Conditons check..."); // Spin until complete (with a timeout) - since this can vary await UntilCondition(TimeSpan.FromSeconds(20), () => { var checkConn = Conn.GetSentinelMasterConnection(ServiceOptions); return(s != checkConn.currentSentinelMasterEndPoint.ToString() && expected == checkConn.GetDatabase().StringGet(key)); }); Log(" Conditions met."); var conn1 = Conn.GetSentinelMasterConnection(ServiceOptions); var s1 = conn1.currentSentinelMasterEndPoint.ToString(); Log("New master endpoint: " + s1); var actual = conn1.GetDatabase().StringGet(key); Log("Fetched tick key: " + actual); Assert.NotNull(s); Assert.NotNull(s1); Assert.NotEmpty(s); Assert.NotEmpty(s1); Assert.NotEqual(s, s1); // TODO: Track this down on the test race //Assert.Equal(expected, actual); }