public string Write(ExecutionResult result) { return JsonConvert.SerializeObject( result, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); }
private void writeData(ExecutionResult result, JsonWriter writer, JsonSerializer serializer) { var data = result.Data; if (result.Errors?.Count > 0 && data == null) { return; } if (result.Errors?.Count > 0) { data = null; } writer.WritePropertyName("data"); serializer.Serialize(writer, data); }
/// <inheritdoc/> public virtual async Task <ExecutionResult> ExecuteAsync(ExecutionOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (options.Schema == null) { throw new InvalidOperationException("Cannot execute request if no schema is specified"); } if (options.Query == null) { throw new InvalidOperationException("Cannot execute request if no query is specified"); } var metrics = (options.EnableMetrics ? new Metrics() : Metrics.None).Start(options.OperationName); ExecutionResult result = null; ExecutionContext context = null; bool executionOccurred = false; try { if (!options.Schema.Initialized) { using (metrics.Subject("schema", "Initializing schema")) { options.Schema.Initialize(); } } var document = options.Document; bool saveInCache = false; bool analyzeComplexity = true; var validationRules = options.ValidationRules; using (metrics.Subject("document", "Building document")) { if (document == null && (document = _documentCache[options.Query]) != null) { // none of the default validation rules yet are dependent on the inputs, and the // operation name is not passed to the document validator, so any successfully cached // document should not need any validation rules run on it validationRules = options.CachedDocumentValidationRules ?? Array.Empty <IValidationRule>(); analyzeComplexity = false; } if (document == null) { document = _documentBuilder.Build(options.Query); saveInCache = true; } } if (document.Operations.Count == 0) { throw new NoOperationError(); } var operation = GetOperation(options.OperationName, document); metrics.SetOperationName(operation?.Name); if (operation == null) { throw new InvalidOperationException($"Query does not contain operation '{options.OperationName}'."); } IValidationResult validationResult; using (metrics.Subject("document", "Validating document")) { validationResult = await _documentValidator.ValidateAsync( options.Query, options.Schema, document, validationRules, options.UserContext, options.Inputs); } if (options.ComplexityConfiguration != null && validationResult.IsValid && analyzeComplexity) { using (metrics.Subject("document", "Analyzing complexity")) _complexityAnalyzer.Validate(document, options.ComplexityConfiguration); } if (saveInCache && validationResult.IsValid) { _documentCache[options.Query] = document; } try { context = BuildExecutionContext( options.Schema, options.Root, document, operation, options.Inputs ?? Inputs.Empty, options.UserContext, options.CancellationToken, metrics, options.Listeners, options.ThrowOnUnhandledException, options.UnhandledExceptionDelegate, options.MaxParallelExecutionCount, options.RequestServices); } catch (InvalidVariableError) { // error parsing variables // attempt to run AfterValidationAsync with null for the 'ExecutionContext.Variables' property context = BuildExecutionContext( options.Schema, options.Root, document, operation, null, options.UserContext, options.CancellationToken, metrics, options.Listeners, options.ThrowOnUnhandledException, options.UnhandledExceptionDelegate, options.MaxParallelExecutionCount, options.RequestServices); try { foreach (var listener in options.Listeners) { await listener.AfterValidationAsync(context, validationResult) .ConfigureAwait(false); } // if there was a validation error, return that, and ignore the variable parsing error if (!validationResult.IsValid) { return(new ExecutionResult { Errors = validationResult.Errors, Perf = metrics.Finish() }); } } catch { // if there was an error within AfterValidationAsync (such as a NullReferenceException // due to ExecutionContext.Variables being null), skip this step and throw the variable parsing error } // if there was no validation errors returned, throw the variable parsing error throw; } foreach (var listener in options.Listeners) { await listener.AfterValidationAsync(context, validationResult) .ConfigureAwait(false); } if (!validationResult.IsValid) { return(new ExecutionResult { Errors = validationResult.Errors, Perf = metrics.Finish() }); } if (context.Errors.Count > 0) { return(new ExecutionResult { Errors = context.Errors, Perf = metrics.Finish() }); } executionOccurred = true; using (metrics.Subject("execution", "Executing operation")) { if (context.Listeners != null) { foreach (var listener in context.Listeners) { await listener.BeforeExecutionAsync(context) .ConfigureAwait(false); } } IExecutionStrategy executionStrategy = SelectExecutionStrategy(context); if (executionStrategy == null) { throw new InvalidOperationException("Invalid ExecutionStrategy!"); } var task = executionStrategy.ExecuteAsync(context) .ConfigureAwait(false); if (context.Listeners != null) { foreach (var listener in context.Listeners) { #pragma warning disable CS0612 // Type or member is obsolete await listener.BeforeExecutionAwaitedAsync(context) #pragma warning restore CS0612 // Type or member is obsolete .ConfigureAwait(false); } } result = await task; if (context.Listeners != null) { foreach (var listener in context.Listeners) { await listener.AfterExecutionAsync(context) .ConfigureAwait(false); } } } result.AddErrors(context.Errors); } catch (OperationCanceledException) when(options.CancellationToken.IsCancellationRequested) { throw; } catch (ExecutionError ex) { (result ??= new ExecutionResult()).AddError(ex); } catch (Exception ex) { if (options.ThrowOnUnhandledException) { throw; } UnhandledExceptionContext exceptionContext = null; if (options.UnhandledExceptionDelegate != null) { exceptionContext = new UnhandledExceptionContext(context, null, ex); options.UnhandledExceptionDelegate(exceptionContext); ex = exceptionContext.Exception; } (result ??= new ExecutionResult()).AddError(ex is ExecutionError executionError ? executionError : new UnhandledError(exceptionContext?.ErrorMessage ?? "Error executing document.", ex)); } finally { result ??= new ExecutionResult(); result.Perf = metrics.Finish(); if (executionOccurred) { result.Executed = true; } context?.Dispose(); } return(result); }
public async Task <ExecutionResult> ExecuteAsync(ExecutionOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } var metrics = new Metrics(options.EnableMetrics); metrics.Start(options.OperationName); options.Schema.FieldNameConverter = options.FieldNameConverter; ExecutionResult result = null; try { ValidateOptions(options); if (!options.Schema.Initialized) { using (metrics.Subject("schema", "Initializing schema")) { if (options.SetFieldMiddleware) { options.FieldMiddleware.ApplyTo(options.Schema); } options.Schema.Initialize(); } } var document = options.Document; using (metrics.Subject("document", "Building document")) { if (document == null) { document = _documentBuilder.Build(options.Query); } } var operation = GetOperation(options.OperationName, document); metrics.SetOperationName(operation?.Name); if (operation == null) { throw new ExecutionError("Unable to determine operation from query."); } IValidationResult validationResult; using (metrics.Subject("document", "Validating document")) { validationResult = _documentValidator.Validate( options.Query, options.Schema, document, options.ValidationRules, options.UserContext, options.Inputs); } if (options.ComplexityConfiguration != null && validationResult.IsValid) { using (metrics.Subject("document", "Analyzing complexity")) _complexityAnalyzer.Validate(document, options.ComplexityConfiguration); } foreach (var listener in options.Listeners) { await listener.AfterValidationAsync( options.UserContext, validationResult, options.CancellationToken) .ConfigureAwait(false); } if (!validationResult.IsValid) { return(new ExecutionResult { Errors = validationResult.Errors, ExposeExceptions = options.ExposeExceptions, Perf = metrics.Finish()?.ToArray() }); } var context = BuildExecutionContext( options.Schema, options.Root, document, operation, options.Inputs, options.UserContext, options.CancellationToken, metrics, options.Listeners, options.ThrowOnUnhandledException); if (context.Errors.Any()) { return(new ExecutionResult { Errors = context.Errors, ExposeExceptions = options.ExposeExceptions, Perf = metrics.Finish()?.ToArray() }); } using (metrics.Subject("execution", "Executing operation")) { foreach (var listener in context.Listeners) { await listener.BeforeExecutionAsync(context.UserContext, context.CancellationToken) .ConfigureAwait(false); } IExecutionStrategy executionStrategy = SelectExecutionStrategy(context); if (executionStrategy == null) { throw new InvalidOperationException("Invalid ExecutionStrategy!"); } var task = executionStrategy.ExecuteAsync(context) .ConfigureAwait(false); foreach (var listener in context.Listeners) { await listener.BeforeExecutionAwaitedAsync(context.UserContext, context.CancellationToken) .ConfigureAwait(false); } result = await task; foreach (var listener in context.Listeners) { await listener.AfterExecutionAsync(context.UserContext, context.CancellationToken) .ConfigureAwait(false); } } if (context.Errors.Any()) { result.Errors = context.Errors; } } catch (Exception ex) { if (options.ThrowOnUnhandledException) { throw; } result = new ExecutionResult { Errors = new ExecutionErrors { new ExecutionError(ex.Message, ex) } }; } finally { result = result ?? new ExecutionResult(); result.ExposeExceptions = options.ExposeExceptions; result.Perf = metrics.Finish()?.ToArray(); } return(result); }
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(); } }