internal void KeepAlive() { var commandMap = Multiplexer.CommandMap; Message msg = null; switch (ConnectionType) { case ConnectionType.Interactive: msg = ServerEndPoint.GetTracerMessage(false); msg.SetSource(ResultProcessor.Tracer, null); break; case ConnectionType.Subscription: if (commandMap.IsAvailable(RedisCommand.UNSUBSCRIBE)) { msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.UNSUBSCRIBE, (RedisChannel)Guid.NewGuid().ToByteArray()); msg.SetSource(ResultProcessor.TrackSubscriptions, null); } break; } if (msg != null) { msg.SetInternalCall(); Multiplexer.Trace("Enqueue: " + msg); if (!TryEnqueue(msg, ServerEndPoint.IsSlave)) { OnInternalError(ExceptionFactory.NoConnectionAvailable(Multiplexer.IncludeDetailInExceptions, Multiplexer.IncludePerformanceCountersInExceptions, msg.Command, msg, ServerEndPoint, Multiplexer.GetServerSnapshot())); } } }
internal void KeepAlive() { if (!(physical?.IsIdle() ?? false)) { return; // don't pile on if already doing something } var commandMap = Multiplexer.CommandMap; Message msg = null; var features = ServerEndPoint.GetFeatures(); switch (ConnectionType) { case ConnectionType.Interactive: msg = ServerEndPoint.GetTracerMessage(false); msg.SetSource(ResultProcessor.Tracer, null); break; case ConnectionType.Subscription: if (commandMap.IsAvailable(RedisCommand.PING) && features.PingOnSubscriber) { msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.PING); msg.SetSource(ResultProcessor.Tracer, null); } else if (commandMap.IsAvailable(RedisCommand.UNSUBSCRIBE)) { msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.UNSUBSCRIBE, (RedisChannel)Multiplexer.UniqueId); msg.SetSource(ResultProcessor.TrackSubscriptions, null); } break; } if (msg != null) { msg.SetInternalCall(); Multiplexer.Trace("Enqueue: " + msg); Multiplexer.OnInfoMessage($"heartbeat ({physical?.LastWriteSecondsAgo}s >= {ServerEndPoint?.WriteEverySeconds}s, {physical?.GetSentAwaitingResponseCount()} waiting) '{msg.CommandAndKey}' on '{PhysicalName}' (v{features.Version})"); physical?.UpdateLastWriteTime(); // pre-emptively #pragma warning disable CS0618 var result = TryWriteSync(msg, ServerEndPoint.IsSlave); #pragma warning restore CS0618 if (result != WriteResult.Success) { var ex = Multiplexer.GetException(result, msg, ServerEndPoint); OnInternalError(ex); } } }
public bool TryResend(int hashSlot, Message message, EndPoint endpoint, bool isMoved) { try { if (ServerType == ServerType.Standalone || hashSlot < 0 || hashSlot >= RedisClusterSlotCount) { return(false); } ServerEndPoint server = multiplexer.GetServerEndPoint(endpoint); if (server != null) { bool retry = false; if ((message.Flags & CommandFlags.NoRedirect) == 0) { message.SetAsking(!isMoved); message.SetNoRedirect(); // once is enough if (isMoved) { message.SetInternalCall(); } // note that everything so far is talking about MASTER nodes; we might be // wanting a SLAVE, so we'll check ServerEndPoint resendVia = null; var command = message.Command; switch (Message.GetMasterSlaveFlags(message.Flags)) { case CommandFlags.DemandMaster: resendVia = server.IsSelectable(command, isMoved) ? server : null; break; case CommandFlags.PreferMaster: resendVia = server.IsSelectable(command, isMoved) ? server : FindSlave(server, command); break; case CommandFlags.PreferSlave: resendVia = FindSlave(server, command, isMoved) ?? (server.IsSelectable(command, isMoved) ? server : null); break; case CommandFlags.DemandSlave: resendVia = FindSlave(server, command, isMoved); break; } if (resendVia == null) { multiplexer.Trace("Unable to resend to " + endpoint); } else { message.PrepareToResend(resendVia, isMoved); retry = resendVia.TryWrite(message) == WriteResult.Success; } } if (isMoved) // update map; note we can still update the map even if we aren't actually goint to resend { var arr = MapForMutation(); var oldServer = arr[hashSlot]; arr[hashSlot] = server; if (oldServer != server) { multiplexer.OnHashSlotMoved(hashSlot, oldServer?.EndPoint, endpoint); } } return(retry); } return(false); } catch { return(false); } }