예제 #1
0
        public ResolverTask(
            IExecutionContext executionContext,
            ObjectType objectType,
            FieldSelection fieldSelection,
            Path path,
            ImmutableStack <object> source,
            OrderedDictionary result)
        {
            _executionContext = executionContext;

            Source         = source;
            ObjectType     = objectType;
            FieldSelection = fieldSelection;
            FieldType      = fieldSelection.Field.Type;
            Path           = path;
            Result         = result;

            ResolverContext = new ResolverContext(
                executionContext, this,
                executionContext.CancellationToken);

            Options = executionContext.Options;

            ExecuteMiddleware = executionContext.GetMiddleware(
                objectType, fieldSelection.Selection);
            HasMiddleware = ExecuteMiddleware != null;
        }
예제 #2
0
        private static async Task ExecuteResolverSeriallyAsync(
            ResolverContext resolverContext,
            Action <ResolverContext> enqueueNext,
            BatchOperationHandler batchOperationHandler,
            IErrorHandler errorHandler,
            CancellationToken cancellationToken)
        {
            resolverContext.Task = ExecuteResolverAsync(
                resolverContext,
                errorHandler);

            if (batchOperationHandler != null)
            {
                await CompleteBatchOperationsAsync(
                    new[] { resolverContext },
                    batchOperationHandler,
                    cancellationToken)
                .ConfigureAwait(false);
            }

            await resolverContext.Task.ConfigureAwait(false);

            // serialize and integrate result into final query result
            var completionContext = new CompleteValueContext(enqueueNext);

            completionContext.CompleteValue(resolverContext);
        }
예제 #3
0
        private async Task ExecuteFieldResolverBatchAsync(
            ExecutionContext executionContext,
            List <FieldResolverTask> batch,
            CancellationToken cancellationToken)
        {
            List <(FieldResolverTask task, IResolverContext context, object resolverResult)> runningTasks =
                new List <(FieldResolverTask, IResolverContext, object)>();

            foreach (FieldResolverTask task in batch)
            {
                IResolverContext resolverContext = new ResolverContext(
                    executionContext, task);
                object resolverResult = task.FieldSelection.Field.Resolver(
                    resolverContext, cancellationToken);
                runningTasks.Add((task, resolverContext, resolverResult));
            }

            foreach (var runningTask in runningTasks)
            {
                FieldSelection fieldSelection = runningTask.task.FieldSelection;
                object         fieldValue     = await CompleteFieldValueAsync(
                    runningTask.resolverResult);

                TryCompleteValue(executionContext, runningTask.context,
                                 runningTask.task.Source,
                                 fieldSelection, fieldSelection.Field.Type,
                                 runningTask.task.Path, fieldValue,
                                 runningTask.task.SetValue);

                cancellationToken.ThrowIfCancellationRequested();
            }
        }
예제 #4
0
        private async Task ExecuteFieldResolverBatchSeriallyAsync(
            ExecutionContext executionContext,
            List <FieldResolverTask> batch,
            CancellationToken cancellationToken)
        {
            List <(FieldResolverTask task, object resolverResult)> runningTasks =
                new List <(FieldResolverTask, object)>();

            foreach (FieldResolverTask task in batch)
            {
                // execute resolver
                IResolverContext resolverContext = new ResolverContext(
                    executionContext, task);
                object resolverResult = task.FieldSelection.Field.Resolver(
                    resolverContext, cancellationToken);

                // complete resolver value
                FieldSelection fieldSelection = task.FieldSelection;
                object         fieldValue     = await CompleteFieldValueAsync(
                    resolverResult);

                TryCompleteValue(executionContext, resolverContext, task.Source,
                                 fieldSelection, fieldSelection.Field.Type,
                                 task.Path, fieldValue,
                                 task.SetValue);

                // execute sub-selection fields normally
                await ExecuteFieldResolversAsync(executionContext, cancellationToken);

                cancellationToken.ThrowIfCancellationRequested();
            }
        }
예제 #5
0
        protected static ResolverContext[] CreateInitialBatch(
            IExecutionContext executionContext,
            IDictionary <string, object> result)
        {
            ImmutableStack <object> source = ImmutableStack <object> .Empty
                                             .Push(executionContext.Operation.RootValue);

            IReadOnlyCollection <FieldSelection> fieldSelections =
                executionContext.CollectFields(
                    executionContext.Operation.RootType,
                    executionContext.Operation.Definition.SelectionSet,
                    null);

            int i = 0;

            ResolverContext[] batch =
                ArrayPool <ResolverContext> .Shared.Rent(
                    fieldSelections.Count);

            foreach (FieldSelection fieldSelection in fieldSelections)
            {
                batch[i++] = ResolverContext.Rent(
                    executionContext,
                    fieldSelection,
                    source,
                    result);
            }

            return(batch);
        }
예제 #6
0
        protected static async Task <IQueryResult> ExecuteQueryAsync(
            IExecutionContext executionContext,
            BatchOperationHandler batchOperationHandler,
            CancellationToken cancellationToken)
        {
            ResolverContext[] initialBatch =
                CreateInitialBatch(executionContext,
                                   executionContext.Result.Data);
            try
            {
                await ExecuteResolversAsync(
                    executionContext,
                    initialBatch,
                    batchOperationHandler,
                    cancellationToken)
                .ConfigureAwait(false);

                EnsureRootValueNonNullState(
                    executionContext.Result,
                    initialBatch);

                return(executionContext.Result);
            }
            finally
            {
                ResolverContext.Return(initialBatch);
                ArrayPool <ResolverContext> .Shared.Return(initialBatch);
            }
        }
예제 #7
0
        public static void CompleteValue(
            this CompleteValueContext completionContext,
            ResolverContext resolverContext)
        {
            if (completionContext == null)
            {
                throw new ArgumentNullException(nameof(completionContext));
            }

            completionContext.ResolverContext = resolverContext;

            ValueCompletion.CompleteValue(
                completionContext,
                resolverContext.Field.Type,
                resolverContext.Result);

            if (completionContext.IsViolatingNonNullType)
            {
                resolverContext.PropagateNonNullViolation.Invoke();
            }
            else
            {
                resolverContext.SetCompletedValue(completionContext.Value);
            }
        }
예제 #8
0
        private async Task ExecuteFieldResolverBatchSeriallyAsync(
            ExecutionContext executionContext,
            List <FieldResolverTask> batch,
            CancellationToken cancellationToken)
        {
            List <(FieldResolverTask task, object resolverResult)> runningTasks =
                new List <(FieldResolverTask, object)>();

            foreach (FieldResolverTask task in batch)
            {
                // execute resolver
                ResolverContext resolverContext = new ResolverContext(
                    executionContext, task);
                object resolverResult = ExecuteFieldResolver(
                    resolverContext, task.FieldSelection.Field,
                    task.FieldSelection.Node, cancellationToken);

                // handle async results
                resolverResult = await HandleFieldValueAsync(
                    resolverResult);

                FieldValueCompletionContext completionContext =
                    new FieldValueCompletionContext(
                        executionContext, resolverContext,
                        task.FieldSelection, task.SetValue,
                        resolverResult);

                CompleteValue(completionContext);

                // execute sub-selection fields normally
                await ExecuteFieldResolversAsync(executionContext, cancellationToken);

                cancellationToken.ThrowIfCancellationRequested();
            }
        }
예제 #9
0
        private ResolverTask(
            ResolverTask parent,
            FieldSelection fieldSelection,
            Path path,
            IImmutableStack <object> source,
            IDictionary <string, object> result,
            Action propagateNonNullViolation)
        {
            _parent           = parent;
            _executionContext = parent._executionContext;
            Source            = source;
            ObjectType        = fieldSelection.Field.DeclaringType;
            FieldSelection    = fieldSelection;
            FieldType         = fieldSelection.Field.Type;
            Path                       = path;
            _result                    = result;
            ScopedContextData          = parent.ScopedContextData;
            _propagateNonNullViolation = propagateNonNullViolation;

            ResolverContext = new ResolverContext(
                parent._executionContext, this,
                parent._executionContext.RequestAborted);

            FieldDelegate = parent._executionContext.FieldHelper
                            .CreateMiddleware(fieldSelection);
        }
예제 #10
0
        private async Task <IExecutionResult> ExecuteMutationAsync(
            IExecutionContext executionContext,
            CancellationToken cancellationToken)
        {
            ResolverContext[] initialBatch =
                CreateInitialBatch(executionContext,
                                   executionContext.Result.Data);

            BatchOperationHandler batchOperationHandler =
                CreateBatchOperationHandler(executionContext);

            try
            {
                await ExecuteResolverBatchSeriallyAsync(
                    executionContext,
                    initialBatch,
                    batchOperationHandler,
                    cancellationToken)
                .ConfigureAwait(false);

                EnsureRootValueNonNullState(
                    executionContext.Result,
                    initialBatch);

                return(executionContext.Result);
            }
            finally
            {
                batchOperationHandler?.Dispose();
                ResolverContext.Return(initialBatch);
                ArrayPool <ResolverContext> .Shared.Return(initialBatch);
            }
        }
예제 #11
0
        public static void CompleteValue(
            Action <ResolverContext> enqueueNext,
            ResolverContext resolverContext)
        {
            CompleteValueContext completionContext = _completionContext.Value;

            completionContext.Clear();

            completionContext.EnqueueNext     = enqueueNext;
            completionContext.ResolverContext = resolverContext;

            CompleteValue(
                completionContext,
                resolverContext.Field.Type,
                resolverContext.Result);

            if (completionContext.IsViolatingNonNullType)
            {
                resolverContext.PropagateNonNullViolation.Invoke();
            }
            else
            {
                resolverContext.SetCompletedValue(completionContext.Value);
            }

            completionContext.Clear();
        }
예제 #12
0
 public void Clear()
 {
     _resolverContext       = null;
     _selection             = null;
     _selectionSet          = null;
     _path                  = null;
     EnqueueNext            = null;
     Value                  = null;
     HasErrors              = false;
     IsViolatingNonNullType = false;
     SetElementNull         = null;
 }
예제 #13
0
        public static ResolverContext Rent(
            IExecutionContext executionContext,
            FieldSelection fieldSelection,
            IImmutableStack <object> source,
            IDictionary <string, object> serializedResult)
        {
            var context = new ResolverContext();

            context.Initialize(
                executionContext,
                fieldSelection,
                source,
                serializedResult);
            return(context);
        }
예제 #14
0
 public ResolverTask(
     IExecutionContext executionContext,
     ObjectType objectType,
     FieldSelection fieldSelection,
     Path path,
     ImmutableStack <object> source,
     OrderedDictionary result)
 {
     Source          = source;
     ObjectType      = objectType;
     FieldSelection  = fieldSelection;
     FieldType       = fieldSelection.Field.Type;
     Path            = path;
     Result          = result;
     ResolverContext = new ResolverContext(executionContext, this);
 }
        private async Task <IExecutionResult> ExecuteInternalAsync(
            IExecutionContext executionContext)
        {
            object rootValue = executionContext.Operation.RootValue;

            FieldSelection fieldSelection = executionContext.CollectFields(
                executionContext.Schema.SubscriptionType,
                executionContext.Operation.Definition.SelectionSet,
                null)
                                            .Single();

            ImmutableStack <object> source = ImmutableStack.Create(rootValue);

            var subscribeContext = ResolverContext.Rent(
                executionContext,
                fieldSelection,
                source,
                new FieldData(1));

            SubscribeResolverDelegate subscribeResolver =
                fieldSelection.Field.SubscribeResolver
                ?? DefaultSubscribeResolverAsync;

            try
            {
                IAsyncEnumerable <object> sourceStream =
                    await subscribeResolver(subscribeContext)
                    .ConfigureAwait(false);

                return(new SubscriptionResult(
                           sourceStream,
                           message =>
                {
                    IExecutionContext cloned = executionContext.Clone();
                    cloned.ContextData[WellKnownContextData.EventMessage] = message;
                    return cloned;
                },
                           ExecuteSubscriptionQueryAsync,
                           executionContext.ServiceScope,
                           executionContext.RequestAborted));
            }
            finally
            {
                ResolverContext.Return(subscribeContext);
            }
        }
예제 #16
0
        private async Task ExecuteFieldResolverBatchAsync(
            ExecutionContext executionContext,
            List <FieldResolverTask> batch,
            CancellationToken cancellationToken)
        {
            List <(FieldResolverTask task, IResolverContext context, object resolverResult)> runningTasks =
                new List <(FieldResolverTask, IResolverContext, object)>();

            foreach (FieldResolverTask task in batch)
            {
                IResolverContext resolverContext = new ResolverContext(
                    executionContext, task);

                if (task.Path.Depth <= _maxExecutionDepth)
                {
                    object resolverResult = ExecuteFieldResolver(
                        resolverContext, task.FieldSelection.Field,
                        task.FieldSelection.Node, cancellationToken);
                    runningTasks.Add((task, resolverContext, resolverResult));
                }
                else
                {
                    runningTasks.Add((task, resolverContext,
                                      new FieldError(
                                          $"The field has a depth of {task.Path.Depth}, " +
                                          "which exceeds max allowed depth of " +
                                          $"{_maxExecutionDepth}", task.FieldSelection.Node)));
                }
            }

            foreach (var runningTask in runningTasks)
            {
                object fieldValue = await HandleFieldValueAsync(
                    runningTask.resolverResult);

                FieldValueCompletionContext completionContext =
                    new FieldValueCompletionContext(
                        executionContext, runningTask.context,
                        runningTask.task.FieldSelection,
                        runningTask.task.SetValue,
                        fieldValue);
                CompleteValue(completionContext);

                cancellationToken.ThrowIfCancellationRequested();
            }
        }
        private void Initialize(
            FieldSelection fieldSelection,
            IImmutableStack <object> source,
            object sourceObject,
            ResolverContext sourceContext,
            FieldData serializedResult,
            Path path,
            Action propagateNonNullViolation)
        {
            _executionContext = sourceContext._executionContext;
            _serializedResult = serializedResult;
            _fieldSelection   = fieldSelection;

            _arguments = fieldSelection.CoerceArguments(
                sourceContext._executionContext.Variables,
                sourceContext._executionContext.Converter);

            Path              = path;
            Source            = source;
            SourceObject      = sourceObject;
            ScopedContextData = sourceContext.ScopedContextData;
            LocalContextData  = ImmutableDictionary <string, object> .Empty;

            bool   isNonNullType = fieldSelection.Field.Type.IsNonNullType();
            Action parentPropagateNonNullViolation = sourceContext.PropagateNonNullViolation;

            PropagateNonNullViolation = () =>
            {
                if (isNonNullType)
                {
                    if (propagateNonNullViolation != null)
                    {
                        propagateNonNullViolation.Invoke();
                    }
                    else if (parentPropagateNonNullViolation != null)
                    {
                        parentPropagateNonNullViolation.Invoke();
                    }
                }
                serializedResult.SetFieldValue(
                    fieldSelection.ResponseIndex,
                    fieldSelection.ResponseName,
                    null);
            };
        }
        public ResolverContext Branch(
            FieldSelection fieldSelection,
            IImmutableStack <object> source,
            object sourceObject,
            IDictionary <string, object> serializedResult,
            Path path,
            Action propagateNonNullViolation)
        {
            ResolverContext branch = Rent(
                fieldSelection,
                source, sourceObject,
                this,
                serializedResult,
                path,
                propagateNonNullViolation);

            return(branch);
        }
예제 #19
0
        private void Initialize(
            FieldSelection fieldSelection,
            IImmutableStack <object> source,
            object sourceObject,
            ResolverContext sourceContext,
            IDictionary <string, object> serializedResult,
            Path path,
            Action propagateNonNullViolation)
        {
            _executionContext = sourceContext._executionContext;
            _serializedResult = serializedResult;
            _fieldSelection   = fieldSelection;

            _arguments = fieldSelection.CoerceArguments(
                sourceContext._executionContext.Variables);

            Path              = path;
            Source            = source;
            SourceObject      = sourceObject;
            ScopedContextData = sourceContext.ScopedContextData;

            bool   isNonNullType = fieldSelection.Field.Type.IsNonNullType();
            string responseName  = fieldSelection.ResponseName;
            Action parentPropagateNonNullViolation =
                sourceContext.PropagateNonNullViolation;

            PropagateNonNullViolation = () =>
            {
                if (isNonNullType)
                {
                    if (propagateNonNullViolation != null)
                    {
                        propagateNonNullViolation.Invoke();
                    }
                    else if (parentPropagateNonNullViolation != null)
                    {
                        parentPropagateNonNullViolation.Invoke();
                    }
                }
                serializedResult[responseName] = null;
            };
        }
        protected static async Task ExecuteResolverAsync(
            ResolverContext resolverContext,
            IErrorHandler errorHandler)
        {
            Activity activity = resolverContext.BeginResolveField();

            await ExecuteMiddlewareAsync(resolverContext, errorHandler)
            .ConfigureAwait(false);

            if (resolverContext.Result is IError singleError)
            {
                resolverContext.ResolverError(singleError);
            }
            else if (resolverContext.Result is IEnumerable <IError> errors)
            {
                resolverContext.ResolverError(errors);
            }

            resolverContext.EndResolveField(activity);
        }
예제 #21
0
        private static async Task EndExecuteResolverBatchAsync(
            IEnumerable <ResolverContext> batch,
            Action <ResolverContext> enqueueNext,
            CancellationToken cancellationToken)
        {
            foreach (ResolverContext resolverContext in batch)
            {
                if (resolverContext.Task.Status != TaskStatus.RanToCompletion)
                {
                    await resolverContext.Task.ConfigureAwait(false);
                }

                ValueCompletion.CompleteValue(enqueueNext, resolverContext);

                if (!resolverContext.IsRoot)
                {
                    ResolverContext.Return(resolverContext);
                }
            }
        }
예제 #22
0
 private static async Task ExecuteMiddlewareAsync(
     ResolverContext resolverContext,
     IErrorHandler errorHandler)
 {
     try
     {
         await resolverContext.Middleware.Invoke(resolverContext)
         .ConfigureAwait(false);
     }
     catch (QueryException ex)
     {
         resolverContext.Result = ex.Errors;
     }
     catch (Exception ex)
     {
         resolverContext.Result =
             errorHandler.CreateUnexpectedError(ex)
             .SetPath(resolverContext.Path)
             .AddLocation(resolverContext.FieldSelection)
             .Build();
     }
 }
예제 #23
0
        private static ResolverContext Rent(
            FieldSelection fieldSelection,
            IImmutableStack <object> source,
            object sourceObject,
            ResolverContext sourceContext,
            IDictionary <string, object> serializedResult,
            Path path,
            Action propagateNonNullViolation)
        {
            // var context = ObjectPools.ResolverContexts.Rent();
            var context = new ResolverContext();

            context.Initialize(
                fieldSelection,
                source,
                sourceObject,
                sourceContext,
                serializedResult,
                path,
                propagateNonNullViolation);
            return(context);
        }
예제 #24
0
        public ResolverTask(
            IExecutionContext executionContext,
            FieldSelection fieldSelection,
            IImmutableStack <object> source,
            IDictionary <string, object> result)
        {
            _executionContext = executionContext;
            Source            = source;
            ObjectType        = fieldSelection.Field.DeclaringType;
            FieldSelection    = fieldSelection;
            FieldType         = fieldSelection.Field.Type;
            Path              = Path.New(fieldSelection.ResponseName);
            _result           = result;
            ScopedContextData = ImmutableDictionary <string, object> .Empty;

            ResolverContext = new ResolverContext(
                executionContext, this,
                executionContext.RequestAborted);

            FieldDelegate = executionContext.FieldHelper
                            .CreateMiddleware(fieldSelection);
        }
        private static async Task ExecuteMiddlewareAsync(
            ResolverContext resolverContext,
            IErrorHandler errorHandler)
        {
            try
            {
                await resolverContext.Middleware.Invoke(resolverContext)
                .ConfigureAwait(false);

                // TODO : this should be handled more elegant
                if (resolverContext.Result is IQueryable q)
                {
                    resolverContext.Result =
                        await Task.Run(() =>
                    {
                        var items = new List <object>();
                        foreach (object o in q)
                        {
                            items.Add(o);
                        }
                        return(items);
                    })
                        .ConfigureAwait(false);
                }
            }
            catch (GraphQLException ex)
            {
                resolverContext.Result = ex.Errors;
            }
            catch (Exception ex)
            {
                resolverContext.Result =
                    errorHandler.CreateUnexpectedError(ex)
                    .SetPath(resolverContext.Path)
                    .AddLocation(resolverContext.FieldSelection)
                    .Build();
            }
        }
예제 #26
0
        private static async Task ExecuteResolverBatchSeriallyAsync(
            IExecutionContext executionContext,
            IEnumerable <ResolverContext> batch,
            BatchOperationHandler batchOperationHandler,
            CancellationToken cancellationToken)
        {
            var next = new List <ResolverContext>();

            foreach (ResolverContext resolverContext in batch)
            {
                if (resolverContext is null)
                {
                    break;
                }

                await ExecuteResolverSeriallyAsync(
                    resolverContext,
                    next.Add,
                    batchOperationHandler,
                    executionContext.ErrorHandler,
                    cancellationToken)
                .ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                // execute child fields with the default parallel flow logic
                await ExecuteResolversAsync(
                    executionContext,
                    next,
                    batchOperationHandler,
                    cancellationToken)
                .ConfigureAwait(false);

                ResolverContext.Return(next);
                next.Clear();
            }
        }
예제 #27
0
        public ResolverTask(
            IExecutionContext executionContext,
            ObjectType objectType,
            FieldSelection fieldSelection,
            Path path,
            IImmutableStack <object> source,
            IDictionary <string, object> result)
        {
            _executionContext = executionContext;
            Source            = source;
            ObjectType        = objectType;
            FieldSelection    = fieldSelection;
            FieldType         = fieldSelection.Field.Type;
            Path    = path;
            _result = result;

            ResolverContext = new ResolverContext(
                executionContext, this,
                executionContext.RequestAborted);

            ExecuteMiddleware = executionContext.FieldHelper.CreateMiddleware(
                objectType, fieldSelection.Selection);
            HasMiddleware = ExecuteMiddleware != null;
        }
예제 #28
0
 public static void Return(ResolverContext rentedContext)
 {
     //ObjectPools.ResolverContexts.Return(rentedContext);
 }