Subscription

Specification

Execution


        [Fact]
        public async Task Subscription()
        {
            /* Given */
            var subscription = Parser.ParseDocument(
                @"subscription {
                    events {
                        __typename
                        id
                        type
                        payload
                    }
                }");

            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

            /* When */
            var result = await Executor.SubscribeAsync(new ExecutionOptions()
            {
                Schema = Schema,
                Document = subscription
            }, cts.Token);

            await Model.AddAsync(new EventsModel.NewEvent()
            {
                Type = EventsModel.EventType.DELETE,
                Payload = "payload1"
            });

            var ev = await result.Source.Reader.ReadAsync(cts.Token);

            // unsubscribe
            cts.Cancel();

            /* Then */
            ev.ShouldMatchJson(
                @"{
                  ""data"": {
                    ""events"": {
                      ""type"": ""DELETE"",
                      ""id"": ""1"",
                      ""__typename"": ""Event"",
                      ""payload"": ""payload1""
                    }
                  }
                }");
        }

Example

These are the schema and resolvers used in the above section.

Schema

Sdl = @"
                enum EventType {
                    INSERT
                    UPDATE
                    DELETE
                }

                type Success {
                    id: ID!
                    event: Event
                }

                type Failure {
                    message: String!
                }

                union Result = Success | Failure

                type Event {
                    id: ID!
                    type: EventType!
                    payload: String
                }

                input NewEvent {
                    type: String!
                    payload: String
                }

                type Query {
                    events: [Event!]
                }

                type Mutation {
                    create(event: NewEvent!): Result
                }

                type Subscription {
                    events: Event!
                }

                schema {
                    query: Query
                    mutation: Mutation
                    subscription: Subscription
                }
                "

Initialization


        public ExecutorFacts(ITestOutputHelper atr)
        {
            Model = new EventsModel();
            Resolvers = new ObjectTypeMap
            {
                {
                    "Success", new FieldResolversMap
                    {
                        {"id", Resolve.PropertyOf<EventsModel.Success>(m => m.Id)},
                        {"event", Resolve.PropertyOf<EventsModel.Success>(m => m.Event)}
                    }
                },
                {
                    "Failure", new FieldResolversMap
                    {
                        {"message", Resolve.PropertyOf<EventsModel.Failure>(m => m.Message)}
                    }
                },
                {
                    "Event", new FieldResolversMap
                    {
                        {"id", Resolve.PropertyOf<EventsModel.Event>(ev => ev.Id)},
                        {"type", Resolve.PropertyOf<EventsModel.Event>(ev => ev.Type)},
                        {"payload", Resolve.PropertyOf<EventsModel.Event>(ev => ev.Payload)}
                    }
                },
                {
                    "NewEvent", new FieldResolversMap
                    {
                        {"type", Resolve.PropertyOf<EventsModel.NewEvent>(type => type.Type)},
                        {"payload", Resolve.PropertyOf<EventsModel.NewEvent>(type => type.Payload)}
                    }
                },
                {
                    "Query", new FieldResolversMap
                    {
                        {"events", context => new ValueTask<IResolverResult>(Resolve.As(Model.Events))}
                    }
                },
                {
                    "Mutation", new FieldResolversMap
                    {
                        {
                            "create", async context =>
                            {
                                var newEvent = context.GetObjectArgument<EventsModel.NewEvent>("event");

                                if (newEvent.Payload == null)
                                    return Resolve.As(
                                        context.ExecutionContext.Schema.GetNamedType<ObjectType>("Failure"),
                                        new EventsModel.Failure("Payload should be given"));

                                var id = await Model.AddAsync(newEvent);
                                var ev = Model.Events.Single(e => e.Id == id);

                                return Resolve.As(
                                    context.ExecutionContext.Schema.GetNamedType<ObjectType>("Success"),
                                    new EventsModel.Success(id, ev));
                            }
                        }
                    }
                },
                {
                    "Subscription", new FieldResolversMap
                    {
                        {
                            "events", async (context, unsubscribe) =>
                            {
                                await Task.Delay(0);
                                var source = Model.Subscribe(unsubscribe);
                                return source;
                            },
                            context => new ValueTask<IResolverResult>(Resolve.As(context.ObjectValue))
                        }
                    }
                }
            };

            Schema = SchemaTools.MakeExecutableSchema(
                new SchemaBuilder().Sdl(Parser.ParseDocument(Sdl)),
                Resolvers,
                Resolvers);
        }