public async Task<ExecutionResult> ExecuteAsync(ExecutionOptions config) { var metrics = new Metrics(); metrics.Start(config.OperationName); config.FieldMiddleware.ApplyTo(config.Schema); var result = new ExecutionResult { Query = config.Query }; try { if (!config.Schema.Initialized) { using (metrics.Subject("schema", "Initializing schema")) { config.Schema.Initialize(); } } var document = config.Document; using (metrics.Subject("document", "Building document")) { if (document == null) { document = _documentBuilder.Build(config.Query); } } result.Document = document; var operation = GetOperation(config.OperationName, document); result.Operation = operation; metrics.SetOperationName(operation?.Name); if (config.ComplexityConfiguration != null) { using (metrics.Subject("document", "Analyzing complexity")) _complexityAnalyzer.Validate(document, config.ComplexityConfiguration); } IValidationResult validationResult; using (metrics.Subject("document", "Validating document")) { validationResult = _documentValidator.Validate( config.Query, config.Schema, document, config.ValidationRules, config.UserContext); } foreach (var listener in config.Listeners) { await listener.AfterValidationAsync( config.UserContext, validationResult, config.CancellationToken) .ConfigureAwait(false); } if (validationResult.IsValid) { var context = BuildExecutionContext( config.Schema, config.Root, document, operation, config.Inputs, config.UserContext, config.CancellationToken, metrics); if (context.Errors.Any()) { result.Errors = context.Errors; return result; } using (metrics.Subject("execution", "Executing operation")) { foreach (var listener in config.Listeners) { await listener.BeforeExecutionAsync(config.UserContext, config.CancellationToken).ConfigureAwait(false); } var task = ExecuteOperationAsync(context).ConfigureAwait(false); foreach (var listener in config.Listeners) { await listener.BeforeExecutionAwaitedAsync(config.UserContext, config.CancellationToken).ConfigureAwait(false); } result.Data = await task; foreach (var listener in config.Listeners) { await listener.AfterExecutionAsync(config.UserContext, config.CancellationToken).ConfigureAwait(false); } } if (context.Errors.Any()) { result.Errors = context.Errors; } } else { result.Data = null; result.Errors = validationResult.Errors; } return result; } catch (Exception exc) { if (result.Errors == null) { result.Errors = new ExecutionErrors(); } result.Data = null; result.Errors.Add(new ExecutionError(exc.Message, exc)); return result; } finally { result.Perf = metrics.Finish().ToArray(); } }