public async Task ExecuteRequestAsync(RequestContext context) { try { // validate if (string.IsNullOrWhiteSpace(context.RawRequest.Query)) { throw new GraphQLException("Query may not be empty."); } Events.OnRequestStarting(context); var handler = new RequestHandler(this, context); await handler.ExecuteAsync(); } catch (AbortRequestException) { return; // error already added to response } catch (InvalidInputException inpEx) { context.AddInputError(inpEx); } catch (Exception ex) { context.AddError(ex); } finally { context.Metrics.Duration = AppTime.GetDuration(context.StartTimestamp); if (context.Failed) { Events.OnRequestError(context); } Events.OnRequestCompleted(context); } }
private async Task ExecuteOperationAsync(GraphQLOperation op, OutputObjectScope topScope) { var mappedTopSubset = op.SelectionSubset.MappedSubSets[0]; var topMappedItems = mappedTopSubset.MappedItems; var parallel = _parallelQueryEnabled && op.OperationType == OperationType.Query && op.SelectionSubset.Items.Count > 1; var executers = new List <OperationFieldExecuter>(); foreach (var mappedItem in topMappedItems) { switch (mappedItem) { case MappedFragmentSpread mfs: _requestContext.AddInputError($"Top selection items may not be fragments", mfs.Spread); return; case MappedSelectionField mappedField: var opExecuter = new OperationFieldExecuter(_requestContext, mappedField, topScope); executers.Add(opExecuter); break; } } if (parallel) { await ExecuteAllParallel(executers); } else { await ExecuteAllNonParallel(executers); } // Save results from op fields into top scope; we do it here, after all threads finished, to avoid concurrency issues // and preserve output field order foreach (var ex in executers) { topScope.SetValue(ex.ResultKey, ex.Result); } }