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); }
/// <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); }
/// <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; }
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]); }