Comments (6)
Thanks a lot @NeedleInAJayStack, that helps a lot.
from graphql-kit.
That's right. This package doesn't have any additional GraphQL subscription functionality. But as the underlying Graphiti and GraphQL packages support subscriptions, you can always use these to implement them in your application.
If you like to create a PR with a generic implementation that helps others to implement GraphQL subscriptions with Vapor faster, that would be great.
I haven't looked into GraphQL subscriptions myself, so I'm not very familiar with them.
from graphql-kit.
Thanks. I looked into this for a few hours, and I don't think I'm going to tackle it right now, it's just a bit above my skill set currently. But if I gain some clarity and understanding in the future, I'd really like to convert my web-socket functionality to GraphQL subscriptions, so I may take a crack at it later.
The underlying mechanisms provided by the Graphiti and GraphQL packages are only scantily documented. I read and re-read the source for those a bunch of times. I think I got a very basic mental model of how it works -- your resolver needs to return a Future of an EventStream<Any>
(which you need to subclass yourself, or pull in a third party package). But implementing the event stream source itself from scratch seems daunting. The documentation recommends pulling in some sort of reactive library, which seems like the way to go. I would lean towards using Combine, but since it doesn't exist on Linux, OpenCombine seems ideal. But I'm just a beginner with Combine, and it's got a bit of a steep learning curve. It seems that one would somehow have to return some kind of Publisher, which publishes values over a web-socket. But how to connect the web-socket connection with an Observable object and keep all those connections straight and thread-safe and connected with the GraphQL schema, seems unclear right now. I'd be curious to know if @NeedleInAJayStack (who implemented the feature in both libraries) built his final production use case in Vapor (or with web sockets as the transport), and had any insight on how to pull it off.
I'm going to implement vanilla web-sockets without GraphQL in my vapor app for now, and my hope is that as my comfort level with those grows (this is my first production implementation of web sockets), and as I learn more about Combine, I might see a way forward.
In the meantime, if you ever want to work on this feature, I'd be happy to try to help, or do some remote pair programming. Really appreciate this library.
from graphql-kit.
Sure, I can provide a little insight. I did build my final app using the normal Vapor websocket implementation, but I didn't use this package - just Graphiti.
In terms of connecting up the observables to websockets, it's not too bad. The steps are this:
- Create a publisher in the subscription field resolver and set it up to publish when a thing happens (in our case, we just publish inside a SQL trigger callback). This publisher is our EventStream.
- Have a Vapor websocket endpoint that clients can connect to and initialize subscriptions.
- When a client requests a subscription, call
API.executeSubscription
. This returns a transformed EventStream that emits fully-resolved graphQL results. - We can add any callbacks we want onto this transformed EventStream, like writing out to the WebSocket that the client initiated.
In my implementation, I copied the protocol used by the javascript graphql-ws to formalize the websocket handshake and make it work with GraphiQL.
The small GraphQLRxSwift package is a wrapper around RxSwift's PubSub functionality - it should be almost exactly the same for a Combine
or OpenCombine
implementation. Really all that's needed is a "transformation" operator on observables so we can transform raw resolver events into fully-resolved GraphQL results.
from graphql-kit.
@NeedleInAJayStack really appreciate you taking the time to chime in. 🙏
So, is there a single, shared, singleton-like publisher for your whole app that publishes when something happens (via the SQL trigger)? Do you then end up basically filtering over the single publisher and emitting events interesting to given web-socket clients based on what they subscribed to?
Or am I misunderstanding, and does each client websocket connection get its own un-shared publisher based on the subscription?
I don't suppose there's any chance your app is open source somewhere where I could poke around the code a bit? If not, would you mind copy/pasting a few lines of the relevant code for each step you mentioned above?
Thanks again!
from graphql-kit.
No problem!
So, is there a single, shared, singleton-like publisher for your whole app
No, we create a fresh PublishSubject in each GraphQL subscription resolver. This is because we want to create and setup SQL triggers based only on what clients have asked for, and then just wrap their callbacks with RxSwift. Yea, the GraphQLRxSwift tests are a little confusing in this case because they use a global PublishSubject because the tests need to have an external handle to cause an event.
Or am I misunderstanding, and does each client websocket connection get its own un-shared publisher based on the subscription?
Yes, this is what we do.
I don't suppose there's any chance your app is open source
Unfortunately it's closed source. The Graphiti GraphQLRxSwift tests are pretty close to what we are doing though, except that in the subscribe resolver we create the PublishSubject
, activate a SQL trigger, and then in the trigger event callback we call PublishSubject.onNext
. It's probably worth noting that we aren't using Fluent and I don't know much about their SQL triggering mechanism.
Hope that helps!
from graphql-kit.
Related Issues (16)
- getting "Cannot complete value of unexpected type X" error with children HOT 5
- Get pivots HOT 2
- Overriding response status code HOT 3
- Error on graphql rout HOT 1
- Date error HOT 4
- Cursor pagination HOT 1
- Selection Set from the Resolver HOT 1
- Any plan to support to async await resolvers ? HOT 5
- Registered GraphQL Schema ignores authenticators HOT 3
- Any plan to upgrade to the latest Graphiti version ? HOT 1
- Enum in GraphQL schema HOT 2
- Can't add parent and child fields to schema due to circular dependency HOT 8
- support for @Sibling many-to-many relationships? HOT 4
- how to use @Timestamp model properties in graphql types HOT 2
- querying @OptionalParent relation HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from graphql-kit.