From 5e85b3773b4c46a24e27fa71d13fd431d9056e01 Mon Sep 17 00:00:00 2001 From: Dylan Dmitri Gray Date: Fri, 17 May 2019 14:27:06 -0700 Subject: [PATCH] ready for final review --- eng/ProjectReferences.props | 2 +- .../RequestThrottling/RequestThrottling.slnf | 25 +++++++ .../RequestThrottling/sample/Startup.cs | 4 +- .../test/SemaphoreWrapperTests.cs | 7 -- .../RequestThrottling/test/TaskExtensions.cs | 69 +++++++++++++++++++ 5 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 src/Middleware/RequestThrottling/RequestThrottling.slnf create mode 100644 src/Middleware/RequestThrottling/test/TaskExtensions.cs diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props index 97f1875b9e..920e15a65e 100644 --- a/eng/ProjectReferences.props +++ b/eng/ProjectReferences.props @@ -79,10 +79,10 @@ - + diff --git a/src/Middleware/RequestThrottling/RequestThrottling.slnf b/src/Middleware/RequestThrottling/RequestThrottling.slnf new file mode 100644 index 0000000000..d434fbc862 --- /dev/null +++ b/src/Middleware/RequestThrottling/RequestThrottling.slnf @@ -0,0 +1,25 @@ +{ + "solution": { + "path": "..\\Middleware.sln", + "projects": [ + "..\\Hosting\\Abstractions\\src\\Microsoft.AspNetCore.Hosting.Abstractions.csproj", + "..\\Hosting\\Hosting\\src\\Microsoft.AspNetCore.Hosting.csproj", + "..\\Hosting\\Server.Abstractions\\src\\Microsoft.AspNetCore.Hosting.Server.Abstractions.csproj", + "..\\Http\\Http.Abstractions\\src\\Microsoft.AspNetCore.Http.Abstractions.csproj", + "..\\Http\\Http.Extensions\\src\\Microsoft.AspNetCore.Http.Extensions.csproj", + "..\\Http\\Http.Features\\src\\Microsoft.AspNetCore.Http.Features.csproj", + "..\\Http\\WebUtilities\\src\\Microsoft.AspNetCore.WebUtilities.csproj", + "..\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj", + "..\\Servers\\Kestrel\\Core\\src\\Microsoft.AspNetCore.Server.Kestrel.Core.csproj", + "..\\Servers\\Kestrel\\Kestrel\\src\\Microsoft.AspNetCore.Server.Kestrel.csproj", + "..\\Servers\\Kestrel\\Transport.Abstractions\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.csproj", + "..\\Servers\\Kestrel\\Transport.Sockets\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj", + "..\\http\\Headers\\src\\Microsoft.Net.Http.Headers.csproj", + "..\\http\\http\\src\\Microsoft.AspNetCore.Http.csproj", + "HttpsPolicy\\src\\Microsoft.AspNetCore.HttpsPolicy.csproj", + "RequestThrottling\\sample\\RequestThrottlingSample.csproj", + "RequestThrottling\\src\\Microsoft.AspNetCore.RequestThrottling.csproj", + "RequestThrottling\\test\\Microsoft.AspNetCore.RequestThrottling.Tests.csproj" + ] + } +} \ No newline at end of file diff --git a/src/Middleware/RequestThrottling/sample/Startup.cs b/src/Middleware/RequestThrottling/sample/Startup.cs index ea4969c9bd..8f0ba344c6 100644 --- a/src/Middleware/RequestThrottling/sample/Startup.cs +++ b/src/Middleware/RequestThrottling/sample/Startup.cs @@ -13,7 +13,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace RequestThrottlingSample -{ +{ public class Startup { // This method gets called by the runtime. Use this method to add services to the container. @@ -26,9 +26,7 @@ namespace RequestThrottlingSample { app.Run(async context => { - Console.WriteLine("HEWWWO?"); await context.Response.WriteAsync("Hello world!"); - Console.WriteLine("GOODBWWYWE!"); }); } diff --git a/src/Middleware/RequestThrottling/test/SemaphoreWrapperTests.cs b/src/Middleware/RequestThrottling/test/SemaphoreWrapperTests.cs index f9ddd80420..b5cdfce18f 100644 --- a/src/Middleware/RequestThrottling/test/SemaphoreWrapperTests.cs +++ b/src/Middleware/RequestThrottling/test/SemaphoreWrapperTests.cs @@ -10,13 +10,6 @@ using Microsoft.AspNetCore.Testing; namespace Microsoft.AspNetCore.RequestThrottling.Tests { - public static class TaskExtensions - { - public static Task OrTimeout(this Task task, int seconds = 30) - { - return task.TimeoutAfter(TimeSpan.FromSeconds(seconds)); - } - } public class SemaphoreWrapperTests { [Fact] diff --git a/src/Middleware/RequestThrottling/test/TaskExtensions.cs b/src/Middleware/RequestThrottling/test/TaskExtensions.cs new file mode 100644 index 0000000000..52ec0c4303 --- /dev/null +++ b/src/Middleware/RequestThrottling/test/TaskExtensions.cs @@ -0,0 +1,69 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using Microsoft.AspNetCore.Testing; + +namespace System.Threading.Tasks +{ +#if TESTUTILS + public +#else + internal +#endif + static class TaskExtensions + { + private const int DefaultTimeout = 30 * 1000; + + public static Task OrTimeout(this Task task, int milliseconds = DefaultTimeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null) + { + return OrTimeout(task, new TimeSpan(0, 0, 0, 0, milliseconds), memberName, filePath, lineNumber); + } + + public static Task OrTimeout(this Task task, TimeSpan timeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null) + { + return task.TimeoutAfter(timeout, filePath, lineNumber ?? 0); + } + + public static Task OrTimeout(this ValueTask task, int milliseconds = DefaultTimeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null) => + OrTimeout(task, new TimeSpan(0, 0, 0, 0, milliseconds), memberName, filePath, lineNumber); + + public static Task OrTimeout(this ValueTask task, TimeSpan timeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null) => + task.AsTask().OrTimeout(timeout, memberName, filePath, lineNumber); + + public static Task OrTimeout(this Task task, int milliseconds = DefaultTimeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null) + { + return OrTimeout(task, new TimeSpan(0, 0, 0, 0, milliseconds), memberName, filePath, lineNumber); + } + + public static Task OrTimeout(this Task task, TimeSpan timeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null) + { + return task.TimeoutAfter(timeout, filePath, lineNumber ?? 0); + } + + public static async Task OrThrowIfOtherFails(this Task task, Task otherTask) + { + var completed = await Task.WhenAny(task, otherTask); + if (completed == otherTask && otherTask.IsFaulted) + { + // Manifest the exception + otherTask.GetAwaiter().GetResult(); + throw new Exception("Unreachable code"); + } + else + { + // Await the task we were asked to await. Either it's finished, or the otherTask finished successfully, and it's not our job to check that + await task; + } + } + + public static async Task OrThrowIfOtherFails(this Task task, Task otherTask) + { + await OrThrowIfOtherFails((Task)task, otherTask); + + // If we get here, 'task' is finished and succeeded. + return task.GetAwaiter().GetResult(); + } + } +}