Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

How can I get GraphQL subscriptions working? #247

Closed
vladimirlogachev opened this issue Nov 8, 2020 · 9 comments · Fixed by #254
Closed

How can I get GraphQL subscriptions working? #247

vladimirlogachev opened this issue Nov 8, 2020 · 9 comments · Fixed by #254
Labels
bug Something isn't working graphQL help wanted Extra attention is needed question Further information is requested

Comments

@vladimirlogachev
Copy link
Contributor

vladimirlogachev commented Nov 8, 2020

There are 2 GraphQL examples, and there are 2 instances of RunDocument in graphql/src/Mu/GraphQL/Query/Run.hs which require (Proxy @('Just sub)).

  • library example (the one with DB) uses one instance (let's call it instance A)
instance
  ( p ~ 'Package pname ss
  , KnownSymbol qr
  , RunQueryFindHandler m p hs chn ss (LookupService ss qr) hs
  , MappingRight chn qr ~ ()
  , KnownSymbol mut
  , RunQueryFindHandler m p hs chn ss (LookupService ss mut) hs
  , MappingRight chn mut ~ ()
  , KnownSymbol sub
  , RunQueryFindHandler m p hs chn ss (LookupService ss sub) hs
  , MappingRight chn sub ~ ()
  , Intro.Introspect p ('Just qr) ('Just mut) ('Just sub)
  ) => RunDocument p ('Just qr) ('Just mut) ('Just sub) m chn hs where
  runDocument f req svr d
    = let i = Intro.introspect (Proxy @p) (Proxy @('Just qr)) (Proxy @('Just mut)) (Proxy @('Just sub))
      in case d of
           QueryDoc q
             -> runQuery f req i svr [] () q
           MutationDoc q
             -> runQuery f req i svr [] () q
           SubscriptionDoc _
             -> pure $ singleErrValue "cannot execute subscriptions in this wire"
  runDocumentSubscription f req svr (SubscriptionDoc d)
    = runSubscription f req svr [] () d
  runDocumentSubscription f req svr d = yieldDocument f req svr d
  • library-graphql example (without DB) uses another instance (let's call it instance B)
instance
  ( p ~ 'Package pname ss
  , KnownSymbol qr
  , RunQueryFindHandler m p hs chn ss (LookupService ss qr) hs
  , MappingRight chn qr ~ ()
  , KnownSymbol sub
  , RunQueryFindHandler m p hs chn ss (LookupService ss sub) hs
  , MappingRight chn sub ~ ()
  , Intro.Introspect p ('Just qr) 'Nothing ('Just sub)
  ) => RunDocument p ('Just qr) 'Nothing ('Just sub) m chn hs where
  runDocument f req svr d
    = let i = Intro.introspect (Proxy @p) (Proxy @('Just qr)) (Proxy @'Nothing) (Proxy @('Just sub))
      in case d of
           QueryDoc q
             -> runQuery f req i svr [] () q
           SubscriptionDoc _
             -> pure $ singleErrValue "cannot execute subscriptions in this wire"
  runDocumentSubscription f req svr (SubscriptionDoc d)
    = runSubscription f req svr [] () d
  runDocumentSubscription f req svr d = yieldDocument f req svr d

Both examples return cannot execute subscriptions in this wire.
I don't quite understand which instance should I aim to use (If I understand it right, there are only 2 for subscriptions defined).

Clients I tried to use:

  1. graphqurl
  2. graphiql

Queries:

  • for library
subscription whatever {
  allBooks {
    id
    title
  }
}
  • for library-graphql
subscription whatever {
  books {
    id
    title
  }
}

(Though I suppose it's a server-side issue, not a client-side).

Please help me understand.

@serras
Copy link
Collaborator

serras commented Nov 9, 2020

How does your server schema look like? The current instances only allow you yo have subscriptions also if you have queries, but there's nothing technical stopping us from creating one only for subscriptions.

@vladimirlogachev
Copy link
Contributor Author

How does your server schema look like?

It's about 2 existing mu-haskell examples. I can't use subscriptions for some reason, which I don't understand.

But I can use graphql subscriptions "in general" - I mean, on the client-side.

@serras
Copy link
Collaborator

serras commented Nov 9, 2020

Usually that means you are asking for subscriptions via HTTP. You need to use a streaming transport, such as WebSockets, to make it work. In most cases, it's as easy as changing http:// for ws://.

@serras
Copy link
Collaborator

serras commented Nov 9, 2020

I am actually not sure how it works over HTTP, if you know of a good pointer to the spec. we could consider adding that support.

@kutyel kutyel added graphQL question Further information is requested labels Nov 9, 2020
@serras
Copy link
Collaborator

serras commented Nov 9, 2020

For example, Apollo requires WebSockets, see the last line in the code block here

@vladimirlogachev
Copy link
Contributor Author

There is a GraphQL over WebSocket Protocol. I would like to mention it here as long as it's related to the topic.

But I still can't figure out how to run subscriptions on existing examples (they are supposed to be working over ws://, right?).

@serras
Copy link
Collaborator

serras commented Nov 10, 2020

Something weird is indeed happening, and I don't know what it is. The code for accepting the connection works OK (I added a few Debug.Trace.traces around). However, whenever receiveJSON in Subscriptions.hs is run, there's always a ConnectionClosed exception trying to receive any message from the client. In theory, that exception is only thrown when the client unilaterally closes the connection (although there are bug reports stating that sometimes those are also raised when the connection is closed gracefully); but here it's always thrown.

Unfortunately, I think we really need to dig deeper, maybe writing a few examples using the websockets library directly; some change in network may have changed how messages are received. We also depend on wai-websockets to expose the server via Warp, this seems like a very thing layer and not so probable, but who knows...

@kutyel kutyel added bug Something isn't working help wanted Extra attention is needed labels Nov 10, 2020
@vladimirlogachev
Copy link
Contributor Author

vladimirlogachev commented Nov 10, 2020

git checkout bfdf5f4

git clean -dxf
stack run library-graphql

Running the simplest example with runGraphQLApp 8000 libraryServer without any headers middleware, Prometheus, database or logger.

...and it still doesn't work.

Do I understand right that it's because dependencies are not specified by their exact versions?

@serras
Copy link
Collaborator

serras commented Nov 11, 2020 via email

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working graphQL help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants