public async Task ReceiveEvent_WithARegisteredClient_ClientRecievesEvent()
        {
            (var server, var socketClient, var apolloClient) = await this.CreateConnection();

            // start the sub on the client
            var startMessage = new ApolloClientStartMessage()
            {
                Id      = "abc",
                Payload = new GraphQueryData()
                {
                    Query = "subscription {  apolloSubscription { watchForPropObject { property1 } } }",
                },
            };

            await apolloClient.DispatchMessage(startMessage);

            var evt = new SubscriptionEvent()
            {
                Data           = new TwoPropertyObject(),
                DataTypeName   = SchemaExtensions.RetrieveFullyQualifiedDataObjectTypeName(typeof(TwoPropertyObject)),
                SchemaTypeName = SchemaExtensions.RetrieveFullyQualifiedSchemaTypeName(typeof(GraphSchema)),
                EventName      = "[subscription]/ApolloSubscription/WatchForPropObject",
            };

            var count = await server.ReceiveEvent(evt);

            Assert.AreEqual(1, count);

            socketClient.AssertApolloResponse(ApolloMessageType.DATA, "abc");
        }
        public async Task ReceiveEvent_OnStartedSubscription_YieldsDataMessage()
        {
            (var socketClient, var apolloClient) = await this.CreateConnection();

            var startMessage = new ApolloClientStartMessage()
            {
                Id      = "abc",
                Payload = new GraphQueryData()
                {
                    Query = "subscription {  apolloSubscription { watchForPropObject { property1 } } }",
                },
            };

            await apolloClient.DispatchMessage(startMessage);

            var route = new GraphFieldPath("[subscription]/ApolloSubscription/WatchForPropObject");
            await apolloClient.ReceiveEvent(route, new TwoPropertyObject()
            {
                Property1 = "value1",
                Property2 = 33,
            });

            socketClient.AssertApolloResponse(
                ApolloMessageType.DATA,
                "abc",
                @"{
                    ""data"" : {
                        ""apolloSubscription"" : {
                            ""watchForPropObject"" : {
                                ""property1"" : ""value1"",
                            }
                        }
                    }
                }");
        }
        public async Task ReceiveEvent_OnNonSubscribedEventNAme_YieldsNothing()
        {
            (var socketClient, var apolloClient) = await this.CreateConnection();

            // start a real subscription so the client is tracking one
            var startMessage = new ApolloClientStartMessage()
            {
                Id      = "abc",
                Payload = new GraphQueryData()
                {
                    Query = "subscription {  apolloSubscription { watchForPropObject { property1 } } }",
                },
            };

            await apolloClient.DispatchMessage(startMessage);

            // fire an event against a route not tracked, ensure the client skips it.
            var route = new GraphFieldPath("[subscription]/ApolloSubscription/WatchForPropObject_NotReal");
            await apolloClient.ReceiveEvent(route, new TwoPropertyObject()
            {
                Property1 = "value1",
                Property2 = 33,
            });

            Assert.AreEqual(0, socketClient.ResponseMessageCount);
        }
        public async Task StartSubscription_ButMessageIsAQuery_YieldsDataMessage()
        {
            (var socketClient, var apolloClient) = await this.CreateConnection();

            // use start message to send a query, not a subscription request
            // client should respond with expected data
            // then a complete
            var startMessage = new ApolloClientStartMessage()
            {
                Id      = "abc",
                Payload = new GraphQueryData()
                {
                    Query = "query {  fastQuery { property1 } }",
                },
            };

            await apolloClient.DispatchMessage(startMessage);

            socketClient.AssertApolloResponse(
                ApolloMessageType.DATA,
                "abc",
                @"{
                    ""data"" : {
                        ""fastQuery"" : {
                            ""property1"" : ""bob""
                        }
                    }
                }");

            socketClient.AssertApolloResponse(ApolloMessageType.COMPLETE);
        }
예제 #5
0
        /// <summary>
        /// Parses the message contents to generate a valid client subscription and adds it to the watched
        /// set for this instance.
        /// </summary>
        /// <param name="message">The message with the subscription details.</param>
        private async Task ExecuteStartRequest(ApolloClientStartMessage message)
        {
            // ensure the id isnt already in use
            if (!_reservedMessageIds.ReserveMessageId(message.Id))
            {
                await this
                .SendMessage(new ApolloServerErrorMessage(
                                 $"The message id {message.Id} is already reserved for an outstanding request and cannot " +
                                 "be processed against. Allow the in-progress request to complete or stop the associated subscription.",
                                 SubscriptionConstants.ErrorCodes.DUPLICATE_MESSAGE_ID,
                                 lastMessage : message,
                                 clientProvidedId : message.Id))
                .ConfigureAwait(false);

                return;
            }

            var retainMessageId = false;
            var runtime         = this.ServiceProvider.GetRequiredService(typeof(IGraphQLRuntime <TSchema>)) as IGraphQLRuntime <TSchema>;
            var request         = runtime.CreateRequest(message.Payload);
            var metricsPackage  = _enableMetrics ? runtime.CreateMetricsPackage() : null;
            var context         = new SubcriptionExecutionContext(
                this,
                request,
                message.Id,
                metricsPackage);

            var result = await runtime
                         .ExecuteRequest(context)
                         .ConfigureAwait(false);

            if (context.IsSubscriptionOperation)
            {
                retainMessageId = await this
                                  .RegisterSubscriptionOrRespond(context.Subscription as ISubscription <TSchema>)
                                  .ConfigureAwait(false);
            }
            else
            {
                // not a subscription, just send back the generated response and close out the id
                ApolloMessage responseMessage;

                // report syntax errors as error messages
                // allow others to bubble into a fully reslt (per apollo spec)
                if (result.Messages.Count == 1 &&
                    result.Messages[0].Code == Constants.ErrorCodes.SYNTAX_ERROR)
                {
                    responseMessage = new ApolloServerErrorMessage(
                        result.Messages[0],
                        message,
                        message.Id);
                }
                else
                {
                    responseMessage = new ApolloServerDataMessage(message.Id, result);
                }

                await this
                .SendMessage(responseMessage)
                .ConfigureAwait(false);

                await this
                .SendMessage(new ApolloServerCompleteMessage(message.Id))
                .ConfigureAwait(false);
            }

            if (!retainMessageId)
            {
                _reservedMessageIds.ReleaseMessageId(message.Id);
            }
        }