protected TransportDisconnectBase(HostContext context, ITransportHeartbeat heartbeat, IPerformanceCounterManager performanceCounterManager, ITraceManager traceManager)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (heartbeat == null)
            {
                throw new ArgumentNullException("heartbeat");
            }

            if (performanceCounterManager == null)
            {
                throw new ArgumentNullException("performanceCounterManager");
            }

            if (traceManager == null)
            {
                throw new ArgumentNullException("traceManager");
            }

            _context = context;
            _heartbeat = heartbeat;
            _counters = performanceCounterManager;

            // Queue to protect against overlapping writes to the underlying response stream
            WriteQueue = new TaskQueue();

            _trace = traceManager["SignalR.Transports." + GetType().Name];
        }
 public HttpRequestLifeTime(TransportDisconnectBase transport, TaskQueue writeQueue, ILogger logger, string connectionId)
 {
     _transport = transport;
     _logger = logger;
     _connectionId = connectionId;
     _writeQueue = writeQueue;
 }
 public HttpRequestLifeTime(TransportDisconnectBase transport, TaskQueue writeQueue, TraceSource trace, string connectionId)
 {
     _transport = transport;
     _trace = trace;
     _connectionId = connectionId;
     _writeQueue = writeQueue;
 }
 public HttpRequestLifeTime(TransportDisconnectBase transport, TaskQueue writeQueue, TraceSource trace, string connectionId)
 {
     _lifetimeTcs = new TaskCompletionSource<object>();
     _transport = transport;
     _trace = trace;
     _connectionId = connectionId;
     _writeQueue = writeQueue;
 }
 public void FailedToEnqueueReturnsNull()
 {
     var queue = new TaskQueue(TaskAsyncHelper.Empty, 2);
     queue.Enqueue(() => Task.Delay(100));
     queue.Enqueue(() => Task.Delay(100));
     Task task = queue.Enqueue(() => Task.Delay(100));
     Assert.Null(task);
 }
        public void DoesNotNotifyMonitorOfInitialTask()
        {
            var mockMonitor = new Mock<ITaskMonitor>();
            var queue = new TaskQueue(TaskAsyncHelper.Empty, mockMonitor.Object);

            mockMonitor.Verify(m => m.TaskStarted(), Times.Never());
            mockMonitor.Verify(m => m.TaskCompleted(), Times.Never());
        }
        public void TaskQueueDoesNotQueueNewTasksIfPreviousTaskFaulted()
        {
            var queue = new TaskQueue();
            queue.Enqueue(() => TaskAsyncHelper.FromError(new Exception()));
            Task task = queue.Enqueue(() => TaskAsyncHelper.Empty);

            Assert.True(task.IsCompleted);
            Assert.True(task.IsFaulted);
        }
        public void DrainingTaskQueueShutsQueueOff()
        {
            var queue = new TaskQueue();
            queue.Enqueue(() => TaskAsyncHelper.Empty);
            queue.Drain();
            Task task = queue.Enqueue(() => TaskAsyncHelper.FromError(new Exception()));

            Assert.True(task.IsCompleted);
            Assert.False(task.IsFaulted);
        }
        public void NotifiesMonitorWhenTaskStartsAndCompletes()
        {
            var mockMonitor = new Mock<ITaskMonitor>();
            var queue = new TaskQueue(TaskAsyncHelper.Empty, mockMonitor.Object);

            queue.Enqueue(() => TaskAsyncHelper.Empty);

            mockMonitor.Verify(m => m.TaskStarted(), Times.Once());
            mockMonitor.Verify(m => m.TaskCompleted(), Times.Once());
        }
        public void DoesNotNotifyMonitorOfCompletionUntilFuncReturns()
        {
            var mockMonitor = new Mock<ITaskMonitor>();
            var queue = new TaskQueue(TaskAsyncHelper.Empty, mockMonitor.Object);

            queue.Enqueue(() =>
            {
                mockMonitor.Verify(m => m.TaskStarted(), Times.Once());
                mockMonitor.Verify(m => m.TaskCompleted(), Times.Never());
                return TaskAsyncHelper.Empty;
            });

            mockMonitor.Verify(m => m.TaskStarted(), Times.Once());
            mockMonitor.Verify(m => m.TaskCompleted(), Times.Once());
        }
        public void TaskQueueRunsTasksInSequence()
        {
            var queue = new TaskQueue();
            int n = 0;
            queue.Enqueue(() =>
            {
                n++;
                return TaskAsyncHelper.Empty;
            });

            Task task = queue.Enqueue(() =>
            {
                return Task.Delay(100).Then(() => n++);
            });

            task.Wait();
            Assert.Equal(n, 2);
        }
        public void DoesNotNotifyMonitorOfCompletionUntilTaskCompletesReturns()
        {
            var mockMonitor = new Mock<ITaskMonitor>();
            var queue = new TaskQueue(TaskAsyncHelper.Empty, mockMonitor.Object);

            var tcs = new TaskCompletionSource<object>();

            queue.Enqueue(() =>
            {
                mockMonitor.Verify(m => m.TaskStarted(), Times.Once());
                return tcs.Task;
            });

            mockMonitor.Verify(m => m.TaskCompleted(), Times.Never());

            tcs.SetResult(null);

            mockMonitor.Verify(m => m.TaskStarted(), Times.Once());
            mockMonitor.Verify(m => m.TaskCompleted(), Times.Once());
        }
        protected TransportDisconnectBase(HttpContext context, ITransportHeartbeat heartbeat, IPerformanceCounterManager performanceCounterManager, IApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory, IMemoryPool pool)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (heartbeat == null)
            {
                throw new ArgumentNullException("heartbeat");
            }

            if (performanceCounterManager == null)
            {
                throw new ArgumentNullException("performanceCounterManager");
            }

            if (applicationLifetime == null)
            {
                throw new ArgumentNullException("applicationLifetime");
            }

            if (loggerFactory == null)
            {
                throw new ArgumentNullException("loggerFactory");
            }

            Pool = pool;

            _context = context;
            _heartbeat = heartbeat;
            _counters = performanceCounterManager;
            _hostShutdownToken = applicationLifetime.ApplicationStopping;
            _requestAborted = context.RequestAborted;

            // Queue to protect against overlapping writes to the underlying response stream
            WriteQueue = new TaskQueue();
            _logger = loggerFactory.CreateLogger(GetType().FullName);
        }
Beispiel #14
0
        /// <summary>
        /// Starts the <see cref="Connection"/>.
        /// </summary>
        /// <param name="transport">The transport to use.</param>
        /// <returns>A task that represents when the connection has started.</returns>
        public Task Start(IClientTransport transport)
        {
            if (transport == null)
            {
                throw new ArgumentNullException("transport");
            }

            lock (_startLock)
            {
                if (!ChangeState(ConnectionState.Disconnected, ConnectionState.Connecting))
                {
                    return _connectTask ?? TaskAsyncHelper.Empty;
                }

                _disconnectCts = new CancellationTokenSource();
                _startTcs = new TaskCompletionSource<object>();
                _receiveQueueMonitor = new TaskQueueMonitor(this, DeadlockErrorTimeout);
                _receiveQueue = new TaskQueue(_startTcs.Task, _receiveQueueMonitor);
                _lastQueuedReceiveTask = TaskAsyncHelper.Empty;

                _transport = transport;

                _connectTask = Negotiate(transport);
            }

            return _connectTask;
        }
 private void InitializeCore()
 {
     Task task = DrainQueue();
     _queue = new TaskQueue(task, _size);
 }
Beispiel #16
0
        /// <summary>
        /// Starts the <see cref="Connection"/>.
        /// </summary>
        /// <param name="transport">The transport to use.</param>
        /// <returns>A task that represents when the connection has started.</returns>
        public Task Start(IClientTransport transport)
        {
            lock (_startLock)
            {
                if (!ChangeState(ConnectionState.Disconnected, ConnectionState.Connecting))
                {
                    return _connectTask ?? TaskAsyncHelper.Empty;
                }

                _disconnectCts = new CancellationTokenSource();
                _startTcs = new TaskCompletionSource<object>();
                _receiveQueue = new TaskQueue(_startTcs.Task);
                _lastQueuedReceiveTask = TaskAsyncHelper.Empty;

                _transport = transport;

                _connectTask = Negotiate(transport);
            }

            return _connectTask;
        }
        public void RequestCompletesAfterFaultedInitializeResponse()
        {
            // Arrange
            var response = new Mock<IResponse>();
            response.Setup(m => m.CancellationToken).Returns(CancellationToken.None);
            var request = new Mock<IRequest>();
            var qs = new NameValueCollection();
            qs["connectionId"] = "1";
            request.Setup(m => m.QueryString).Returns(new NameValueCollectionWrapper(qs));
            request.Setup(m => m.LocalPath).Returns("/test/echo/connect");
            var counters = new PerformanceCounterManager();
            var heartBeat = new Mock<ITransportHeartbeat>();
            var json = new JsonSerializer();
            var hostContext = new HostContext(request.Object, response.Object);
            var transportConnection = new Mock<ITransportConnection>();
            var traceManager = new Mock<ITraceManager>();
            traceManager.Setup(m => m[It.IsAny<string>()]).Returns(new System.Diagnostics.TraceSource("foo"));

            transportConnection.Setup(m => m.Receive(It.IsAny<string>(),
                                                     It.IsAny<Func<PersistentResponse, object, Task<bool>>>(),
                                                     It.IsAny<int>(),
                                                     It.IsAny<object>()))
                .Returns<string, Func<PersistentResponse, object, Task<bool>>, int, object>(
                    (messageId, callback, maxMessages, state) =>
                        new DisposableAction(() => callback(new PersistentResponse(), state))
                    );

            var transport = new Mock<ForeverTransport>(hostContext, json, heartBeat.Object, counters, traceManager.Object)
            {
                CallBase = true
            };

            var queue = new TaskQueue();

            transport.Setup(t => t.EnqueueOperation(It.IsAny<Func<object, Task>>(), It.IsAny<object>()))
                .Returns<Func<object, Task>, object>(
                    (writeAsync, state) => queue.Enqueue(writeAsync, state));

            transport.Setup(t => t.InitializeResponse(It.IsAny<ITransportConnection>()))
                .Returns<ITransportConnection>(
                    pr => TaskAsyncHelper.FromError(new Exception()));

            transport.Setup(t => t.Send(It.IsAny<PersistentResponse>()))
                .Returns<PersistentResponse>(
                    pr => transport.Object.EnqueueOperation(() => TaskAsyncHelper.Empty));

            var tcs = new TaskCompletionSource<bool>();
            transport.Object.AfterRequestEnd = (ex) =>
            {
                // Trip the cancellation token
                tcs.TrySetResult(transport.Object.WriteQueue.IsDrained);
            };

            // Act
            transport.Object.ProcessRequest(transportConnection.Object);

            // Assert
            Assert.True(tcs.Task.Wait(TimeSpan.FromSeconds(2)));
            Assert.True(tcs.Task.Result);
        }
        public void InitializeResponseIsFirstEnqueuedOperation()
        {
            // Arrange
            var response = new Mock<IResponse>();
            response.Setup(m => m.CancellationToken).Returns(CancellationToken.None);
            var request = new Mock<IRequest>();
            var qs = new NameValueCollection();
            qs["connectionId"] = "1";
            request.Setup(m => m.QueryString).Returns(new NameValueCollectionWrapper(qs));
            request.Setup(m => m.LocalPath).Returns("/test/echo/connect");
            var counters = new Mock<IPerformanceCounterManager>();
            var heartBeat = new Mock<ITransportHeartbeat>();
            var json = new JsonSerializer();
            var hostContext = new HostContext(request.Object, response.Object);
            var transportConnection = new Mock<ITransportConnection>();
            var traceManager = new Mock<ITraceManager>();
            counters.SetupGet(m => m.ConnectionsConnected).Returns(new NoOpPerformanceCounter());
            counters.SetupGet(m => m.ErrorsTransportTotal).Returns(new NoOpPerformanceCounter());
            counters.SetupGet(m => m.ErrorsTransportPerSec).Returns(new NoOpPerformanceCounter());
            counters.SetupGet(m => m.ErrorsAllTotal).Returns(new NoOpPerformanceCounter());
            counters.SetupGet(m => m.ErrorsAllPerSec).Returns(new NoOpPerformanceCounter());
            traceManager.Setup(m => m[It.IsAny<string>()]).Returns(new System.Diagnostics.TraceSource("foo"));

            transportConnection.Setup(m => m.Receive(It.IsAny<string>(),
                                                     It.IsAny<Func<PersistentResponse, object, Task<bool>>>(),
                                                     It.IsAny<int>(),
                                                     It.IsAny<object>()))
                .Returns<string, Func<PersistentResponse, object, Task<bool>>, int, object>(
                    (messageId, callback, maxMessages, state) => 
                    {
                        callback(new PersistentResponse(), state);
                        return DisposableAction.Empty;
                    });

            var transport = new Mock<ForeverTransport>(hostContext, json, heartBeat.Object, counters.Object, traceManager.Object)
            {
                CallBase = true
            };

            var queue = new TaskQueue();
            var results = new List<string>();

            transport.Setup(t => t.EnqueueOperation(It.IsAny<Func<object, Task>>(), It.IsAny<object>()))
                .Returns<Func<object, Task>, object>(
                    (writeAsync, state) =>
                    {
                        return queue.Enqueue(writeAsync, state);
                    });

            transport.Setup(t => t.InitializeResponse(It.IsAny<ITransportConnection>()))
                .Returns<ITransportConnection>(
                    pr =>
                    {
                        results.Add("InitializeResponse");
                        return TaskAsyncHelper.Empty;
                    });

            transport.Setup(t => t.Send(It.IsAny<PersistentResponse>()))
                .Returns<PersistentResponse>(
                    pr =>
                        transport.Object.EnqueueOperation(() =>
                        {
                            results.Add("Send");
                            return TaskAsyncHelper.Empty;
                        }));

            // Act
            transport.Object.ProcessRequest(transportConnection.Object);

            // Assert
            Assert.Equal("InitializeResponse", results[0]);
            Assert.Equal("Send", results[1]);
        }
        public void RequestCompletesAfterFaultedInitializeResponse()
        {
            // Arrange
            var testContext = new TestContext("/test/echo/connect");
            var counters = new PerformanceCounterManager(new Mock<ILoggerFactory>().Object);
            var heartBeat = new Mock<ITransportHeartbeat>();
            var json = new JsonSerializer();
            var transportConnection = new Mock<ITransportConnection>();
            var loggerFactory = new Mock<ILoggerFactory>();
            var memoryPool = new Mock<IMemoryPool>();
            var applicationLifetime = new Mock<IApplicationLifetime>();
            applicationLifetime.SetupGet(m => m.ApplicationStopping).Returns(CancellationToken.None);

            var logger = new Mock<ILogger>();
            loggerFactory.Setup(m => m.CreateLogger(It.IsAny<string>())).Returns(logger.Object);

            transportConnection.Setup(m => m.Receive(It.IsAny<string>(),
                                                     It.IsAny<Func<PersistentResponse, object, Task<bool>>>(),
                                                     It.IsAny<int>(),
                                                     It.IsAny<object>()))
                .Returns<string, Func<PersistentResponse, object, Task<bool>>, int, object>(
                    (messageId, callback, maxMessages, state) =>
                        new DisposableAction(() => callback(new PersistentResponse(), state))
                    );

            var transport = new Mock<ForeverTransport>(testContext.MockHttpContext.Object, json, heartBeat.Object, counters, applicationLifetime.Object, loggerFactory.Object, memoryPool.Object)
            {
                CallBase = true
            };

            var queue = new TaskQueue();

            transport.Setup(t => t.EnqueueOperation(It.IsAny<Func<object, Task>>(), It.IsAny<object>()))
                .Returns<Func<object, Task>, object>(
                    (writeAsync, state) => queue.Enqueue(writeAsync, state));

            transport.Setup(t => t.InitializeResponse(It.IsAny<ITransportConnection>()))
                .Returns<ITransportConnection>(
                    pr => TaskAsyncHelper.FromError(new Exception()));

            transport.Setup(t => t.Send(It.IsAny<PersistentResponse>()))
                .Returns<PersistentResponse>(
                    pr => transport.Object.EnqueueOperation(() => TaskAsyncHelper.Empty));

            var tcs = new TaskCompletionSource<bool>();
            transport.Object.AfterRequestEnd = (ex) =>
            {
                // Trip the cancellation token
                tcs.TrySetResult(transport.Object.WriteQueue.IsDrained);
            };

            // Act
            transport.Object.ProcessRequest(transportConnection.Object);

            // Assert
            Assert.True(tcs.Task.Wait(TimeSpan.FromSeconds(2)));
            Assert.True(tcs.Task.Result);
        }
        private static Task Drain(TaskQueue queue, ILogger logger)
        {
            if (queue == null)
            {
                return TaskAsyncHelper.Empty;
            }

            var tcs = new TaskCompletionSource<object>();

            queue.Drain().Catch(logger).ContinueWith(task =>
            {
                tcs.SetResult(null);
            });

            return tcs.Task;
        }
 public HttpRequestLifeTime(TaskQueue writeQueue, TraceSource trace, string connectionId)
 {
     _trace = trace;
     _connectionId = connectionId;
     _writeQueue = writeQueue;
 }
Beispiel #22
0
        protected override void InitializePersistentState()
        {
            // PersistentConnection.OnConnectedAsync must complete before we can write to the output stream,
            // so clients don't indicate the connection has started too early.
            InitializeTcs = new TaskCompletionSource<object>();
            WriteQueue = new TaskQueue(InitializeTcs.Task);

            base.InitializePersistentState();
        }
        protected override void InitializePersistentState()
        {
            // PersistentConnection.OnConnected must complete before we can write to the output stream,
            // so clients don't indicate the connection has started too early.
            InitializeTcs = new TaskCompletionSource<object>();

            // WriteQueue must be reinitialized before calling base.InitializePersistentState to ensure
            // _requestLifeTime will be properly initialized.
            WriteQueue = new TaskQueue(InitializeTcs.Task);

            base.InitializePersistentState();

            // The _transportLifetime must be initialized after calling base.InitializePersistentState since
            // _transportLifetime depends on _requestLifetime.
            _transportLifetime = new RequestLifetime(this, _requestLifeTime);
        }
 private void InitializeCore()
 {
     if (UsingTaskQueue)
     {
         Task task = DrainPreviousQueue();
         _queue = new TaskQueue(task, _size);
         _queue.QueueSizeCounter = _perfCounters.ScaleoutSendQueueLength;
     }
 }
        public void InitializeResponseIsFirstEnqueuedOperation()
        {
            // Arrange
            var testContext = new TestContext("/test/echo/connect");
            var counters = new Mock<IPerformanceCounterManager>();
            var heartBeat = new Mock<ITransportHeartbeat>();
            var json = new JsonSerializer();
            var transportConnection = new Mock<ITransportConnection>();
            var loggerFactory = new Mock<ILoggerFactory>();
            var memoryPool = new Mock<IMemoryPool>();
            counters.SetupGet(m => m.ConnectionsConnected).Returns(new NoOpPerformanceCounter());
            counters.SetupGet(m => m.ErrorsTransportTotal).Returns(new NoOpPerformanceCounter());
            counters.SetupGet(m => m.ErrorsTransportPerSec).Returns(new NoOpPerformanceCounter());
            counters.SetupGet(m => m.ErrorsAllTotal).Returns(new NoOpPerformanceCounter());
            counters.SetupGet(m => m.ErrorsAllPerSec).Returns(new NoOpPerformanceCounter());

            var applicationLifetime = new Mock<IApplicationLifetime>();
            applicationLifetime.SetupGet(m => m.ApplicationStopping).Returns(CancellationToken.None);

            var logger = new Mock<ILogger>();

            transportConnection.Setup(m => m.Receive(It.IsAny<string>(),
                                                     It.IsAny<Func<PersistentResponse, object, Task<bool>>>(),
                                                     It.IsAny<int>(),
                                                     It.IsAny<object>()))
                .Returns<string, Func<PersistentResponse, object, Task<bool>>, int, object>(
                    (messageId, callback, maxMessages, state) =>
                    {
                        callback(new PersistentResponse(), state);
                        return DisposableAction.Empty;
                    });

            var transport = new Mock<ForeverTransport>(testContext.MockHttpContext.Object, json, heartBeat.Object, counters.Object, applicationLifetime.Object, loggerFactory.Object, memoryPool.Object)
            {
                CallBase = true
            };

            var queue = new TaskQueue();
            var results = new List<string>();

            transport.Setup(t => t.EnqueueOperation(It.IsAny<Func<object, Task>>(), It.IsAny<object>()))
                .Returns<Func<object, Task>, object>(
                    (writeAsync, state) =>
                    {
                        return queue.Enqueue(writeAsync, state);
                    });

            transport.Setup(t => t.InitializeResponse(It.IsAny<ITransportConnection>()))
                .Returns<ITransportConnection>(
                    pr =>
                    {
                        results.Add("InitializeResponse");
                        return TaskAsyncHelper.Empty;
                    });

            transport.Setup(t => t.Send(It.IsAny<PersistentResponse>()))
                .Returns<PersistentResponse>(
                    pr =>
                        transport.Object.EnqueueOperation(() =>
                        {
                            results.Add("Send");
                            return TaskAsyncHelper.Empty;
                        }));

            // Act
            transport.Object.ProcessRequest(transportConnection.Object);

            // Assert
            Assert.Equal("InitializeResponse", results[0]);
            Assert.Equal("Send", results[1]);
        }