Ejemplo n.º 1
0
            private async ValueTask <ISourceStream> SubscribeAsync()
            {
                OperationContext operationContext = _operationContextPool.Get();

                try
                {
                    object?rootValue = RootValueResolver.TryResolve(
                        _requestContext,
                        _requestContext.Services,
                        _subscriptionType,
                        ref _cachedRootValue);

                    operationContext.Initialize(
                        _requestContext,
                        _requestContext.Services,
                        NoopBatchDispatcher.Default,
                        _requestContext.Operation !,
                        rootValue,
                        _requestContext.Variables !);

                    ResultMap          resultMap     = operationContext.Result.RentResultMap(1);
                    IPreparedSelection rootSelection = _rootSelections[0];

                    var middlewareContext = new MiddlewareContext();
                    middlewareContext.Initialize(
                        operationContext,
                        _rootSelections[0],
                        resultMap,
                        1,
                        rootValue,
                        Path.New(_rootSelections[0].ResponseName),
                        ImmutableDictionary <string, object?> .Empty);

                    ISourceStream sourceStream =
                        await rootSelection.Field.SubscribeResolver !.Invoke(middlewareContext)
                        .ConfigureAwait(false);

                    if (operationContext.Result.Errors.Count > 0)
                    {
                        throw new GraphQLException(operationContext.Result.Errors);
                    }

                    return(sourceStream);
                }
                finally
                {
                    operationContext.Result.DropResult();
                    _operationContextPool.Return(operationContext);
                }
            }
Ejemplo n.º 2
0
            private async Task <IReadOnlyQueryResult> OnEvent(object payload)
            {
                using IServiceScope serviceScope = _requestContext.Services.CreateScope();

                IServiceProvider eventServices = serviceScope.ServiceProvider;
                IBatchDispatcher dispatcher    = eventServices.GetRequiredService <IBatchDispatcher>();

                OperationContext operationContext = _operationContextPool.Get();

                try
                {
                    var scopedContext = ImmutableDictionary <string, object?> .Empty
                                        .SetItem(WellKnownContextData.EventMessage, payload);

                    object?rootValue = RootValueResolver.TryResolve(
                        _requestContext,
                        eventServices,
                        _subscriptionType,
                        ref _cachedRootValue);

                    operationContext.Initialize(
                        _requestContext,
                        eventServices,
                        dispatcher,
                        _requestContext.Operation !,
                        rootValue,
                        _requestContext.Variables !);

                    return(await _queryExecutor.ExecuteAsync(operationContext, scopedContext)
                           .ConfigureAwait(false));
                }
                finally
                {
                    _operationContextPool.Return(operationContext);
                }
            }
Ejemplo n.º 3
0
        // subscribe will use the subscribe resolver to create a source stream that yields
        // the event messages from the underlying pub/sub-system.
        private async ValueTask <ISourceStream> SubscribeAsync()
        {
            OperationContext operationContext = _operationContextPool.Get();

            try
            {
                // first we will create the root value which essentially
                // is the subscription object. In some cases this object is null.
                var rootValue = RootValueResolver.Resolve(
                    _requestContext,
                    _requestContext.Services,
                    _subscriptionType,
                    ref _cachedRootValue);

                // next we need to initialize our operation context so that we have access to
                // variables services and other things.
                // The subscribe resolver will use a noop dispatcher and all DataLoader are
                // dispatched immediately.
                operationContext.Initialize(
                    _requestContext,
                    _requestContext.Services,
                    NoopBatchDispatcher.Default,
                    _requestContext.Operation !,
                    _queryPlan,
                    _requestContext.Variables !,
                    rootValue,
                    _resolveQueryRootValue);

                // next we need a result map so that we can store the subscribe temporarily
                // while executing the subscribe pipeline.
                ResultMap  resultMap     = operationContext.Result.RentResultMap(1);
                ISelection rootSelection = _rootSelections.Selections[0];

                // we create a temporary middleware context so that we can use the standard
                // resolver pipeline.
                var middlewareContext = new MiddlewareContext();
                middlewareContext.Initialize(
                    operationContext,
                    rootSelection,
                    resultMap,
                    1,
                    rootValue,
                    Path.New(rootSelection.ResponseName),
                    ImmutableDictionary <string, object?> .Empty);

                // it is important that we correctly coerce the arguments before
                // invoking subscribe.
                if (!rootSelection.Arguments.TryCoerceArguments(
                        middlewareContext,
                        out IReadOnlyDictionary <NameString, ArgumentValue>?coercedArgs))
                {
                    // the middleware context reports errors to the operation context,
                    // this means if we failed, we need to grab the coercion errors from there
                    // and just throw a GraphQLException.
                    throw new GraphQLException(operationContext.Result.Errors);
                }

                // if everything is fine with the arguments we still need to assign them.
                middlewareContext.Arguments = coercedArgs;

                // last but not least we can invoke the subscribe resolver which will subscribe
                // to the underlying pub/sub-system yielding the source stream.
                ISourceStream sourceStream =
                    await rootSelection.Field.SubscribeResolver !.Invoke(middlewareContext)
                    .ConfigureAwait(false);

                if (operationContext.Result.Errors.Count > 0)
                {
                    // again if we have any errors we will just throw them and not opening
                    // any subscription context.
                    throw new GraphQLException(operationContext.Result.Errors);
                }

                return(sourceStream);
            }
            catch
            {
                // if there is an error we will just dispose our instrumentation scope
                // the error is reported in the request level in this case.
                _subscriptionScope?.Dispose();
                _subscriptionScope = null;
                throw;
            }
            finally
            {
                operationContext.Result.DropResult();
                _operationContextPool.Return(operationContext);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// OnEvent is called whenever the event stream yields a payload and triggers an
        /// execution of the subscription query.
        /// </summary>
        /// <param name="payload">
        /// The event stream payload.
        /// </param>
        /// <returns>
        /// Returns a query result which will be enqueued to the response stream.
        /// </returns>
        private async Task <IQueryResult> OnEvent(object payload)
        {
            using IDisposable es             = _diagnosticEvents.OnSubscriptionEvent(new(this, payload));
            using IServiceScope serviceScope = _requestContext.Services.CreateScope();

            OperationContext operationContext = _operationContextPool.Get();

            try
            {
                IServiceProvider?eventServices = serviceScope.ServiceProvider;
                IBatchDispatcher?dispatcher    = eventServices.GetRequiredService <IBatchDispatcher>();

                // we store the event payload on the scoped context so that it is accessible
                // in the resolvers.
                ImmutableDictionary <string, object?> scopedContext =
                    ImmutableDictionary <string, object?> .Empty
                    .SetItem(WellKnownContextData.EventMessage, payload);

                // next we resolve the subscription instance.
                var rootValue = RootValueResolver.Resolve(
                    _requestContext,
                    eventServices,
                    _subscriptionType,
                    ref _cachedRootValue);

                // last we initialize a standard operation context to execute
                // the subscription query with the standard query executor.
                operationContext.Initialize(
                    _requestContext,
                    eventServices,
                    dispatcher,
                    _requestContext.Operation !,
                    _queryPlan,
                    _requestContext.Variables !,
                    rootValue,
                    _resolveQueryRootValue);

                operationContext.Result.SetContextData(
                    WellKnownContextData.EventMessage,
                    payload);

                IQueryResult result = await _queryExecutor
                                      .ExecuteAsync(operationContext, scopedContext)
                                      .ConfigureAwait(false);

                _diagnosticEvents.SubscriptionEventResult(new(this, payload), result);

                return(result);
            }
            catch (Exception ex)
            {
                _diagnosticEvents.SubscriptionEventError(
                    new SubscriptionEventContext(this, payload),
                    ex);
                throw;
            }
            finally
            {
                _operationContextPool.Return(operationContext);
            }
        }