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); } } }
internal override Task <T> ExecuteAsync <T>(Message message, ResultProcessor <T> processor, ServerEndPoint server = null) { if (message == null) { return(CompletedTask <T> .Default(asyncState)); } multiplexer.CheckMessage(message); // prepare the inner command as a task Task <T> task; if (message.IsFireAndForget) { task = CompletedTask <T> .Default(null); // F+F explicitly does not get async-state } else { var source = TaskResultBox <T> .Create(out var tcs, asyncState); task = tcs.Task; message.SetSource(source, processor); } // store it (pending ?? (pending = new List <Message>())).Add(message); return(task); }
internal ValueTask WriteDirectOrQueueFireAndForgetAsync <T>(PhysicalConnection connection, Message message, ResultProcessor <T> processor) { async ValueTask Awaited(ValueTask <WriteResult> l_result) => await l_result.ForAwait(); if (message != null) { message.SetSource(processor, null); ValueTask <WriteResult> result; if (connection == null) { Multiplexer.Trace("Enqueue: " + message); result = GetBridge(message.Command).TryWriteAsync(message, isSlave); } else { Multiplexer.Trace("Writing direct: " + message); var bridge = connection.BridgeCouldBeNull; if (bridge == null) { throw new ObjectDisposedException(connection.ToString()); } else { result = bridge.WriteMessageTakingWriteLockAsync(connection, message); } } if (!result.IsCompletedSuccessfully) { return(Awaited(result)); } } return(default);
internal Task <T> WriteDirectAsync <T>(Message message, ResultProcessor <T> processor, object asyncState = null, PhysicalBridge bridge = null) { var source = TaskResultBox <T> .Create(out var tcs, asyncState); message.SetSource(processor, source); if (bridge == null) { bridge = GetBridge(message.Command); } WriteResult result; if (bridge == null) { result = WriteResult.NoConnectionAvailable; } else { var write = bridge.TryWriteAsync(message, isSlave); if (!write.IsCompletedSuccessfully) { return(WriteDirectAsync_Awaited <T>(this, message, write, tcs)); } result = write.Result; } if (result != WriteResult.Success) { var ex = Multiplexer.GetException(result, message, this); ConnectionMultiplexer.ThrowFailed(tcs, ex); } return(tcs.Task); }
internal void WriteDirectOrQueueFireAndForget <T>(PhysicalConnection connection, Message message, ResultProcessor <T> processor) { if (message != null) { message.SetSource(processor, null); if (connection == null) { Multiplexer.Trace("Enqueue: " + message); GetBridge(message.Command).TryWrite(message, isSlave); } else { Multiplexer.Trace("Writing direct: " + message); var bridge = connection.BridgeCouldBeNull; if (bridge == null) { throw new ObjectDisposedException(connection.ToString()); } else { bridge.WriteMessageTakingWriteLock(connection, message); } } } }
internal void QueueDirectFireAndForget <T>(Message message, ResultProcessor <T> processor, PhysicalBridge bridge = null) { if (message != null) { message.SetSource(processor, null); multiplexer.Trace("Enqueue: " + message); (bridge ?? GetBridge(message.Command)).TryEnqueue(message, isSlave); } }
internal override Task <T> ExecuteAsync <T>(Message message, ResultProcessor <T> processor, ServerEndPoint server = null) { if (message == null) { return(CompletedTask <T> .Default(asyncState)); } multiplexer.CheckMessage(message); multiplexer.Trace("Wrapping " + message.Command, "Transaction"); // prepare the inner command as a task Task <T> task; if (message.IsFireAndForget) { task = CompletedTask <T> .Default(null); // F+F explicitly does not get async-state } else { var tcs = TaskSource.Create <T>(asyncState); var source = ResultBox <T> .Get(tcs); message.SetSource(source, processor); task = tcs.Task; } // prepare an outer-command that decorates that, but expects QUEUED var queued = new QueuedMessage(message); var wasQueued = ResultBox <bool> .Get(null); queued.SetSource(wasQueued, QueuedProcessor.Default); // store it, and return the task of the *outer* command // (there is no task for the inner command) lock (SyncLock) { (_pending ?? (_pending = new List <QueuedMessage>())).Add(queued); switch (message.Command) { case RedisCommand.UNKNOWN: case RedisCommand.EVAL: case RedisCommand.EVALSHA: // people can do very naughty things in an EVAL // including change the DB; change it back to what we // think it should be! var sel = PhysicalConnection.GetSelectDatabaseCommand(message.Db); queued = new QueuedMessage(sel); wasQueued = ResultBox <bool> .Get(null); queued.SetSource(wasQueued, QueuedProcessor.Default); _pending.Add(queued); break; } } return(task); }
internal void WriteDirectFireAndForgetSync <T>(Message message, ResultProcessor <T> processor, PhysicalBridge bridge = null) { if (message != null) { message.SetSource(processor, null); Multiplexer.Trace("Enqueue: " + message); #pragma warning disable CS0618 (bridge ?? GetBridge(message.Command)).TryWriteSync(message, isSlave); #pragma warning restore CS0618 } }
internal Task <T> QueueDirectAsync <T>(Message message, ResultProcessor <T> processor, object asyncState = null, PhysicalBridge bridge = null) { var tcs = TaskSource.CreateDenyExecSync <T>(asyncState); var source = ResultBox <T> .Get(tcs); message.SetSource(processor, source); if (!(bridge ?? GetBridge(message.Command)).TryEnqueue(message, isSlave)) { ConnectionMultiplexer.ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(multiplexer.IncludeDetailInExceptions, message.Command, message, this)); } return(tcs.Task); }
internal Task <T> QueueDirectAsync <T>(Message message, ResultProcessor <T> processor, object asyncState = null, PhysicalBridge bridge = null) { var tcs = TaskSource.Create <T>(asyncState); var source = ResultBox <T> .Get(tcs); message.SetSource(processor, source); if (bridge == null) { bridge = GetBridge(message.Command); } if (!bridge.TryEnqueue(message, isSlave)) { ConnectionMultiplexer.ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(Multiplexer.IncludeDetailInExceptions, Multiplexer.IncludePerformanceCountersInExceptions, message.Command, message, this, Multiplexer.GetServerSnapshot())); } return(tcs.Task); }
internal void WriteDirectOrQueueFireAndForget <T>(PhysicalConnection connection, Message message, ResultProcessor <T> processor) { if (message != null) { message.SetSource(processor, null); if (connection == null) { multiplexer.Trace("Enqueue: " + message); GetBridge(message.Command).TryEnqueue(message, isSlave); } else { multiplexer.Trace("Writing direct: " + message); connection.Bridge.WriteMessageDirect(connection, message); } } }
internal Task <T> WriteDirectAsync <T>(Message message, ResultProcessor <T> processor, object asyncState = null, PhysicalBridge bridge = null) { var tcs = TaskSource.Create <T>(asyncState); var source = ResultBox <T> .Get(tcs); message.SetSource(processor, source); if (bridge == null) { bridge = GetBridge(message.Command); } var result = bridge.TryWrite(message, isSlave); if (result != WriteResult.Success) { var ex = Multiplexer.GetException(result, message, this); ConnectionMultiplexer.ThrowFailed(tcs, ex); } return(tcs.Task); }