Fix long polling graceful shutdown (#476)

- If a message was sent and the application was ended in the same
poll request, the connection would be closed by the time the next poll
came in which resulted in a 404. This change waits until the transport writes
all data before closing it.
- Also fixed a test so that the exception started to show client side.

#469
This commit is contained in:
David Fowler 2017-05-22 09:07:26 -07:00 committed by GitHub
parent 323dae4ce9
commit e68a1b294f
2 changed files with 28 additions and 5 deletions

View File

@ -207,13 +207,35 @@ namespace Microsoft.AspNetCore.Sockets
var resultTask = await Task.WhenAny(state.ApplicationTask, state.TransportTask);
// If the application ended before the transport task then we need to end the connection completely
// so there is no future polling
var pollAgain = true;
// If the application ended before the transport task then we need to potentially need to end the
// connection
if (resultTask == state.ApplicationTask)
{
await _manager.DisposeAndRemoveAsync(state);
// Complete the transport (notifying it of the application error if there is one)
state.Connection.Transport.Output.TryComplete(state.ApplicationTask.Exception);
// Wait for the transport to run
await state.TransportTask;
// If the status code is a 204 it means we didn't write anything
if (context.Response.StatusCode == StatusCodes.Status204NoContent)
{
// We should be able to safely dispose because there's no more data being written
await _manager.DisposeAndRemoveAsync(state);
// Don't poll again if we've removed the connection completely
pollAgain = false;
}
}
else if (!resultTask.IsCanceled)
else if (resultTask.IsCanceled)
{
// Don't poll if the transport task was cancelled
pollAgain = false;
}
if (pollAgain)
{
// Otherwise, we update the state to inactive again and wait for the next poll
try

View File

@ -104,12 +104,13 @@ namespace Microsoft.AspNetCore.SignalR.Tests
if (e != null)
{
receiveTcs.TrySetException(e);
closeTcs.TrySetException(e);
}
else
{
receiveTcs.TrySetResult(null);
closeTcs.TrySetResult(null);
}
closeTcs.TrySetResult(null);
};
logger.LogInformation("Starting connection to {url}", url);