{"action":"opened","issue":{"url":"https://api.github.com/repos/haskell-graphql/graphql-api/issues/203","repository_url":"https://api.github.com/repos/haskell-graphql/graphql-api","labels_url":"https://api.github.com/repos/haskell-graphql/graphql-api/issues/203/labels{/name}","comments_url":"https://api.github.com/repos/haskell-graphql/graphql-api/issues/203/comments","events_url":"https://api.github.com/repos/haskell-graphql/graphql-api/issues/203/events","html_url":"https://github.com/haskell-graphql/graphql-api/issues/203","id":357490557,"node_id":"MDU6SXNzdWUzNTc0OTA1NTc=","number":203,"title":"Thinking about Subscriptions","user":{"login":"RichardWarfield","id":4101168,"node_id":"MDQ6VXNlcjQxMDExNjg=","avatar_url":"https://avatars1.githubusercontent.com/u/4101168?v=4","gravatar_id":"","url":"https://api.github.com/users/RichardWarfield","html_url":"https://github.com/RichardWarfield","followers_url":"https://api.github.com/users/RichardWarfield/followers","following_url":"https://api.github.com/users/RichardWarfield/following{/other_user}","gists_url":"https://api.github.com/users/RichardWarfield/gists{/gist_id}","starred_url":"https://api.github.com/users/RichardWarfield/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RichardWarfield/subscriptions","organizations_url":"https://api.github.com/users/RichardWarfield/orgs","repos_url":"https://api.github.com/users/RichardWarfield/repos","events_url":"https://api.github.com/users/RichardWarfield/events{/privacy}","received_events_url":"https://api.github.com/users/RichardWarfield/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-09-06T04:17:31Z","updated_at":"2018-09-06T04:17:31Z","closed_at":null,"author_association":"NONE","body":"I'd like to help with adding GraphQL subscriptions support to this package.  I have started porting the [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws) package for subscriptions over WebSockets to Haskell [here](https://github.com/RichardWarfield/graphql-subscriptions-ws).  There's a sample application and GraphiQL frontend for testing.\r\n\r\nThe below discussion is about the issues encountered in creating an implementation of subscriptions with `graphql-api`.  TL;DR: I can't quite follow the spec on subscription execution due to the lack of an `initialValue` concept in `graphql-api` resolvers/handlers.  I've implemented a workaround and would like to get feedback from the `graphql-api` authors/community.\r\n\r\n-------\r\n\r\nFor graphql-api to support subscriptions in terms of syntax and validation, the changes are pretty trivial and obvious (see my [fork](https://github.com/RichardWarfield/graphql-api)).  \r\n\r\nExecution is tricker.  Unlike for queries or mutations, the section in the [spec](http://facebook.github.io/graphql/June2018/#sec-Subscription) on executing subscriptions is pretty long and detailed.  For reasons explained below, I don't believe it is possible to follow the spec's execution methodology closely in graphql-api (at least without significant and annoying changes).\r\n\r\nTo summarize my understanding of the spec (and simplifying greatly), a subscription should be executed as follows:\r\n\r\n1. A stream of \"source events\" is created using the resolver for the subscription type in the schema\r\n2. Each source event triggers an execution of the subscription selection set using the source event as a root value, using the function called (in the spec) [ExecuteSelectionSet](http://facebook.github.io/graphql/June2018/#ExecuteSelectionSet())\r\n\r\nIn my example app, the source stream is just a clock that pushes the current time to the stream each second.  Under the spec's methodolgy, each timestamp would get passed to ExecuteSelectionSet as the initial value, which in turn calls the field resolvers which also receive the initial value.\r\n\r\nIn `graphql-api` there isn't the concept of an initial value passed to resolvers/handlers.  I suppose this could be added but it would break a lot of stuff and be ugly.  \r\n\r\nThe workaround I've used in the sample app is, instead of passing the source event as an initialValue (which doesn't exist in graphql-api), I instead pass it as an Argument.  So my root schema looks like:\r\n\r\n```haskell\r\ntype GQLRoot = Object \"GQLRoot\" '[]\r\n  '[\r\n  Argument \"sourceEvent\" Int32 :> Field \"now\" Now\r\n   ]\r\n```\r\n\r\nThen when a user issues a subscription `subscription sub { now { ... } }`, it is converted into a query like `{ now(sourceEvent: <TIMESTAMP>) {...} }, which gets executed once for each source event (i.e. the time stamp).\r\n\r\nI'm not sure whether this is the best approach to take for executing subscriptions.  I can think of several issues off the top of my head  The extra argument is ugly, and end users might see the \"wrong\" schema -- though some type synonyms / `newtypes` and simple schema transformations could fix these problems.  "}}
{"actor":{"display_login":"RichardWarfield"}}