Allow configuration of SPA startup timeout. Part of #1447

This commit is contained in:
Steve Sanderson
2018-01-02 14:13:47 +00:00
parent a98c1459b5
commit 814441c933
4 changed files with 15 additions and 10 deletions

View File

@@ -20,7 +20,6 @@ namespace Microsoft.AspNetCore.SpaServices.AngularCli
{ {
private const string LogCategoryName = "Microsoft.AspNetCore.SpaServices"; private const string LogCategoryName = "Microsoft.AspNetCore.SpaServices";
private static TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(5); // This is a development-time only feature, so a very long timeout is fine private static TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(5); // This is a development-time only feature, so a very long timeout is fine
private static TimeSpan StartupTimeout = TimeSpan.FromSeconds(50); // Note that the HTTP request itself by default times out after 60s, so you only get useful error information if this is shorter
public static void Attach( public static void Attach(
ISpaBuilder spaBuilder, ISpaBuilder spaBuilder,
@@ -54,9 +53,10 @@ namespace Microsoft.AspNetCore.SpaServices.AngularCli
{ {
// On each request, we create a separate startup task with its own timeout. That way, even if // On each request, we create a separate startup task with its own timeout. That way, even if
// the first request times out, subsequent requests could still work. // the first request times out, subsequent requests could still work.
return targetUriTask.WithTimeout(StartupTimeout, var timeout = spaBuilder.Options.StartupTimeout;
return targetUriTask.WithTimeout(timeout,
$"The Angular CLI process did not start listening for requests " + $"The Angular CLI process did not start listening for requests " +
$"within the timeout period of {StartupTimeout.Seconds} seconds. " + $"within the timeout period of {timeout.Seconds} seconds. " +
$"Check the log output for error information."); $"Check the log output for error information.");
}); });
} }

View File

@@ -24,8 +24,6 @@ namespace Microsoft.AspNetCore.Builder
/// </summary> /// </summary>
public static class SpaPrerenderingExtensions public static class SpaPrerenderingExtensions
{ {
private static TimeSpan BuildTimeout = TimeSpan.FromSeconds(50); // Note that the HTTP request itself by default times out after 60s, so you only get useful error information if this is shorter
/// <summary> /// <summary>
/// Enables server-side prerendering middleware for a Single Page Application. /// Enables server-side prerendering middleware for a Single Page Application.
/// </summary> /// </summary>
@@ -71,6 +69,7 @@ namespace Microsoft.AspNetCore.Builder
var excludePathStrings = (options.ExcludeUrls ?? Array.Empty<string>()) var excludePathStrings = (options.ExcludeUrls ?? Array.Empty<string>())
.Select(url => new PathString(url)) .Select(url => new PathString(url))
.ToArray(); .ToArray();
var buildTimeout = spaBuilder.Options.StartupTimeout;
applicationBuilder.Use(async (context, next) => applicationBuilder.Use(async (context, next) =>
{ {
@@ -93,9 +92,9 @@ namespace Microsoft.AspNetCore.Builder
// For better debuggability, create a per-request timeout that makes it clear if the // For better debuggability, create a per-request timeout that makes it clear if the
// prerendering builder took too long for this request, but without aborting the // prerendering builder took too long for this request, but without aborting the
// underlying build task so that subsequent requests could still work. // underlying build task so that subsequent requests could still work.
await buildOnDemandTask.WithTimeout(BuildTimeout, await buildOnDemandTask.WithTimeout(buildTimeout,
$"The prerendering build process did not complete within the " + $"The prerendering build process did not complete within the " +
$"timeout period of {BuildTimeout.Seconds} seconds. " + $"timeout period of {buildTimeout.Seconds} seconds. " +
$"Check the log output for error information."); $"Check the log output for error information.");
} }

View File

@@ -19,7 +19,6 @@ namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer
{ {
private const string LogCategoryName = "Microsoft.AspNetCore.SpaServices"; private const string LogCategoryName = "Microsoft.AspNetCore.SpaServices";
private static TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(5); // This is a development-time only feature, so a very long timeout is fine private static TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(5); // This is a development-time only feature, so a very long timeout is fine
private static TimeSpan StartupTimeout = TimeSpan.FromSeconds(50); // Note that the HTTP request itself by default times out after 60s, so you only get useful error information if this is shorter
public static void Attach( public static void Attach(
ISpaBuilder spaBuilder, ISpaBuilder spaBuilder,
@@ -53,9 +52,10 @@ namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer
{ {
// On each request, we create a separate startup task with its own timeout. That way, even if // On each request, we create a separate startup task with its own timeout. That way, even if
// the first request times out, subsequent requests could still work. // the first request times out, subsequent requests could still work.
return targetUriTask.WithTimeout(StartupTimeout, var timeout = spaBuilder.Options.StartupTimeout;
return targetUriTask.WithTimeout(timeout,
$"The create-react-app server did not start listening for requests " + $"The create-react-app server did not start listening for requests " +
$"within the timeout period of {StartupTimeout.Seconds} seconds. " + $"within the timeout period of {timeout.Seconds} seconds. " +
$"Check the log output for error information."); $"Check the log output for error information.");
}); });
} }

View File

@@ -67,5 +67,11 @@ namespace Microsoft.AspNetCore.SpaServices
/// development. The directory may not exist in published applications. /// development. The directory may not exist in published applications.
/// </summary> /// </summary>
public string SourcePath { get; set; } public string SourcePath { get; set; }
/// <summary>
/// Gets or sets the maximum duration that a request will wait for the SPA
/// to become ready to serve to the client.
/// </summary>
public TimeSpan StartupTimeout { get; set; } = TimeSpan.FromSeconds(50);
} }
} }