private async Task ExecuteOperationAsync(GraphQLOperation op, OutputObjectScope topScope) { var opOutItemSet = op.SelectionSubset.MappedItemSets.FirstOrDefault(fi => fi.ObjectTypeDef == op.OperationTypeDef); var topFields = _requestContext.GetIncludedMappedFields(opOutItemSet); topScope.Init(op.OperationTypeDef, topFields); var parallel = _parallelQuery && op.OperationType == OperationType.Query && topFields.Count > 1; // Note: if we go parallel here, note that the topScope is safe for concurrent thread access; // it is only used to save op result value (SetValue method) var executers = new List <OperationFieldExecuter>(); for (int fieldIndex = 0; fieldIndex < topFields.Count; fieldIndex++) { var opExecuter = new OperationFieldExecuter(_requestContext, topScope, fieldIndex); executers.Add(opExecuter); } _requestContext.Metrics.ExecutionThreadCount = executers.Count; if (parallel) { await ExecuteAllParallel(executers); } else { await ExecuteAllNonParallel(executers); } }
public object CreateObjectFieldResultScope(object entity, RequestPath path) { // special case - Union if (TypeDef.Kind == TypeKind.Union) { if (entity is UnionBase ub) { entity = ub.Value; } if (entity == null) { return(null); } } var entType = entity.GetType(); var mapping = TypeDef.FindMapping(entType); if (mapping == null) { throw new FatalServerException($"FATAL: failed to find mapping for entity type {entType} in the type {TypeDef.Name}. "); } var scope = new OutputObjectScope(path, entity, mapping); AllResultScopes.Add(scope); var newCount = Interlocked.Increment(ref _requestContext.Metrics.OutputObjectCount); // check total count against quota if (newCount > _requestContext.Quota.MaxOutputObjects) { this.ThrowObjectCountExceededQuota(); } return(scope); }
public async Task ExecuteAsync() { if (!ParseBuildRequest()) { return; } AssignRequestOperation(); if (_requestContext.Failed) { return; } // signal to prepare/deserialize variables; in http/web scenario, we cannot parse variables immediately - // we do not know variable types yet. Now that we have parsed and prepared query, we have var types; // we fire this event, parent GraphQLHttpServer will handle it and deserializer variables. _server.Events.OnRequestPrepared(_requestContext); BuildOperationVariables(); if (_requestContext.Failed) { return; } var topScope = new OutputObjectScope(); // we do not count it as an 'output object', so no incr of object count in metrics _requestContext.Response.Data = topScope; await ExecuteOperationAsync(_requestContext.Operation, topScope); }
public OperationFieldExecuter(RequestContext requestContext, OutputObjectScope parentScope, int fieldIndex) { _requestContext = requestContext; _parentScope = parentScope; _fieldIndex = fieldIndex; _operationField = _parentScope.Fields[_fieldIndex]; }
public object CreateObjectFieldResultScopes(object rawResult, int rank, RequestPath path) { if (rawResult == null) { return(null); } // check field depth against quota if (path.FieldDepth > _requestContext.Quota.MaxDepth) { this.ThrowFieldDepthExceededQuota(); } switch (rank) { case 0: var typeDef = Field.FieldDef.TypeRef.TypeDef; // special cases - Union, Interface; extract actual value from box switch (typeDef.Kind) { case TypeKind.Union: if (rawResult is UnionBase ub) { rawResult = ub.Value; } if (rawResult == null) { return(null); } break; case TypeKind.Interface: if (rawResult == null) { return(null); } break; } var scope = new OutputObjectScope(this, path, rawResult); AllResultScopes.Add(scope); var newCount = Interlocked.Increment(ref _requestContext.Metrics.OutputObjectCount); // check total count against quota if (newCount > _requestContext.Quota.MaxOutputObjects) { this.ThrowObjectCountExceededQuota(); } return(scope); default: // rank > 0, array var list = rawResult as IList; var scopes = new object[list.Count]; for (int i = 0; i < list.Count; i++) { scopes[i] = CreateObjectFieldResultScopes(list[i], rank - 1, path.Append(i)); } return(scopes); } }
private ObjectTypeDef GetMappedObjectTypeDef(OutputObjectScope scope) { object entity = scope.Entity; var typeDef = _requestContext.ApiModel.GetMappedGraphQLType(entity.GetType()); if (typeDef == null || typeDef.Kind != TypeKind.Object) { // TODO: see if it can happen we can throw better error here } return((ObjectTypeDef)typeDef); }
internal void SetCurrentParentScope(OutputObjectScope scope) { _currentParentScope = scope; }
public OperationFieldExecuter(RequestContext requestContext, MappedSelectionField mappedOpField, OutputObjectScope parentScope) { _requestContext = requestContext; _parentScope = parentScope; _mappedOpField = mappedOpField; }