예제 #1
0
        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()));
                }
            }
        }
예제 #2
0
        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);
                }
            }
        }
예제 #3
0
        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);
     }
 }
예제 #8
0
        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
            }
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
 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);
        }