When a SPA dev server (or prerendering build) takes too long to start up, only fail current request, not future requests. Fixes #1447

This commit is contained in:
Steve Sanderson
2018-01-02 14:02:10 +00:00
parent 975d537a0a
commit a98c1459b5
7 changed files with 75 additions and 40 deletions

View File

@@ -11,6 +11,7 @@ using System.IO;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SpaServices.Extensions.Util;
namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer
{
@@ -48,7 +49,15 @@ namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer
var targetUriTask = portTask.ContinueWith(
task => new UriBuilder("http", "localhost", task.Result).Uri);
SpaProxyingExtensions.UseProxyToSpaDevelopmentServer(spaBuilder, targetUriTask);
SpaProxyingExtensions.UseProxyToSpaDevelopmentServer(spaBuilder, () =>
{
// 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.
return targetUriTask.WithTimeout(StartupTimeout,
$"The create-react-app server did not start listening for requests " +
$"within the timeout period of {StartupTimeout.Seconds} seconds. " +
$"Check the log output for error information.");
});
}
private static async Task<int> StartCreateReactAppServerAsync(
@@ -75,8 +84,7 @@ namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer
// no compiler warnings. So instead of waiting for that, consider it ready as soon
// as it starts listening for requests.
await npmScriptRunner.StdOut.WaitForMatch(
new Regex("Starting the development server", RegexOptions.None, RegexMatchTimeout),
StartupTimeout);
new Regex("Starting the development server", RegexOptions.None, RegexMatchTimeout));
}
catch (EndOfStreamException ex)
{
@@ -85,13 +93,6 @@ namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer
$"create-react-app server was listening for requests. The error output was: " +
$"{stdErrReader.ReadAsString()}", ex);
}
catch (TaskCanceledException ex)
{
throw new InvalidOperationException(
$"The create-react-app server did not start listening for requests " +
$"within the timeout period of {StartupTimeout.Seconds} seconds. " +
$"Check the log output for error information.", ex);
}
}
return portNumber;