Lazy create ResourceInvoker.InvokeAsync statemachine

This commit is contained in:
Ben Adams 2019-04-12 03:00:28 +01:00 committed by Ryan Nowak
parent 7a4400e3b2
commit fe6907616b
1 changed files with 118 additions and 25 deletions

View File

@ -57,46 +57,139 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
_cursor = new FilterCursor(filters); _cursor = new FilterCursor(filters);
} }
public virtual async Task InvokeAsync() public virtual Task InvokeAsync()
{ {
if (_diagnosticListener.IsEnabled() || _logger.IsEnabled(LogLevel.Information))
{
return Logged(this);
}
_actionContextAccessor.ActionContext = _actionContext;
var scope = _logger.ActionScope(_actionContext.ActionDescriptor);
Exception invokeException = null;
Task task = null;
try try
{ {
_actionContextAccessor.ActionContext = _actionContext; task = InvokeFilterPipelineAsync();
}
catch (Exception ex)
{
invokeException = ex;
}
_diagnosticListener.BeforeAction( if (invokeException != null)
_actionContext.ActionDescriptor, {
_actionContext.HttpContext, return Awaited(this, Task.FromException(invokeException), scope);
_actionContext.RouteData); }
using (_logger.ActionScope(_actionContext.ActionDescriptor)) Debug.Assert(task != null);
if (!task.IsCompletedSuccessfully)
{
return Awaited(this, task, scope);
}
Exception releaseException = null;
try
{
ReleaseResources();
}
catch (Exception ex)
{
releaseException = ex;
}
Exception scopeException = null;
try
{
scope.Dispose();
}
catch (Exception ex)
{
scopeException = ex;
}
if (releaseException == null && scopeException == null)
{
return Task.CompletedTask;
}
else if (releaseException != null && scopeException != null)
{
return Task.FromException(new AggregateException(releaseException, scopeException));
}
else if (releaseException != null)
{
return Task.FromException(releaseException);
}
else
{
return Task.FromException(scopeException);
}
static async Task Awaited(ResourceInvoker invoker, Task task, IDisposable scope)
{
try
{ {
_logger.ExecutingAction(_actionContext.ActionDescriptor);
_logger.AuthorizationFiltersExecutionPlan(_filters);
_logger.ResourceFiltersExecutionPlan(_filters);
_logger.ActionFiltersExecutionPlan(_filters);
_logger.ExceptionFiltersExecutionPlan(_filters);
_logger.ResultFiltersExecutionPlan(_filters);
var stopwatch = ValueStopwatch.StartNew();
try try
{ {
await InvokeFilterPipelineAsync(); await task;
} }
finally finally
{ {
ReleaseResources(); invoker.ReleaseResources();
_logger.ExecutedAction(_actionContext.ActionDescriptor, stopwatch.GetElapsedTime());
} }
} }
finally
{
scope.Dispose();
}
} }
finally
static async Task Logged(ResourceInvoker invoker)
{ {
_diagnosticListener.AfterAction( var actionContext = invoker._actionContext;
_actionContext.ActionDescriptor, invoker._actionContextAccessor.ActionContext = actionContext;
_actionContext.HttpContext,
_actionContext.RouteData); try
{
var logger = invoker._logger;
invoker._diagnosticListener.BeforeAction(
actionContext.ActionDescriptor,
actionContext.HttpContext,
actionContext.RouteData);
using (logger.ActionScope(actionContext.ActionDescriptor))
{
logger.ExecutingAction(actionContext.ActionDescriptor);
var filters = invoker._filters;
logger.AuthorizationFiltersExecutionPlan(filters);
logger.ResourceFiltersExecutionPlan(filters);
logger.ActionFiltersExecutionPlan(filters);
logger.ExceptionFiltersExecutionPlan(filters);
logger.ResultFiltersExecutionPlan(filters);
var stopwatch = ValueStopwatch.StartNew();
try
{
await invoker.InvokeFilterPipelineAsync();
}
finally
{
invoker.ReleaseResources();
logger.ExecutedAction(actionContext.ActionDescriptor, stopwatch.GetElapsedTime());
}
}
}
finally
{
invoker._diagnosticListener.AfterAction(
actionContext.ActionDescriptor,
actionContext.HttpContext,
actionContext.RouteData);
}
} }
} }