Apollo-Server GraphQL Subscription on External WebSocket Server - websocket

So I have a bit of a question since I'm having a hard time wrapping my head around it. Currently I have a GraphQL API Server created using Apollo-Server and persisted using a local sqlite database. I have the queries and mutations working correctly.
I also have an external WebSocket server that constantly has messages (that match my GraphQL/Database schema) produced to it at say ws://localhost:8000/websocket. Is it possible to have my GraphQL Server subscribe to that websocket address and constantly parse those messages and use the appropriate mutation to insert into the backend database?
I would then have a Vue frontend that would constantly display the results (via Vue Apollo Clients WS subscription maybe?)

to have my GraphQL Server subscribe to that websocket address and constantly parse those messages
Typically no, its the other way around - you can make ws server to call graphql server to do the mutations. That is if you want to use WS as the primary transport layer for everything - queries, mutations & subscriptions.
But usually architecture separates queries & mutations because they are more stateless and critical from subscriptions which are more stateful (persisted connection)
client -> queries & mutations -> graphql server --> redis pubsub -+
|
client <--> subscriptions <-- graphql subscription server <-------+
(in simpler cases when you don't need high load, you can combine both servers to use in-memory pubsub)
BUT, if you very much want to, ofc you can write custom code to connect graphql server -> listen ws server in the background. See https://github.com/enisdenjo/graphql-ws#node-client for example
The problem can appear if you have some user context. You would need to either have custom connection where changes of all users happen. Or have a dedicated connection for every user

Yes , it can be done quite easily , just write a service worker or a worker thread that constantly checks for new messages
Can be done using worker_threads in node js
And if you need to implement it realtime
Make sure your worker thread starts a socket connection and is constantly connected to the port where you are publishing your messages
You can do it using socket.io library

Related

Should socket.io server update the database?

I’m bulilding a web app that requires communication between clients. For this I’m using socket.io. Some data however has to be updated regularly in the database.
Some of them not that often (preferences, on button click) others in every second for example a timer value. This can not be calculated because the timer can be paused.
Right now whenever a client emits an event, it also makes a request to the backend to updated the database. I was wondering if it would be a good idea to have the socket.io server update the database so the clients would only have to take care of the socket communication? It seems to me that having the browser do a request to the backend is a bit resource heavy and takes out a bit from the advantages of the socket based communication
Edit: the back end of the app and the socket server are two different servers but physically they are on the same machine so their communication could be faster
the main point of using socket.io is that it allows you to push data to clients and clients do not need to check your server constantly to get the last changes, and providing a low-overhead communication channel between the server and the client.
you can call an API and also emit data and many other things on user click in your application.
it is a good idea to have the socket.io server update the database and you can also authorize each socket, save client sockets information and ...

AWS AppSync over websockets for query, mutation, and subscription (no REST)?

I've been successful with Apollo Server + graphql-ws for using a websocket as the entire network transport (all queries, mutations, and subscriptions). Is this possible to do with AWS AppSync? Or does AWS AppSync only allow use of the websocket for subscriptions and all queries/mutations go via REST requests?
Allowing queries and mutations to go over the websocket (which is already connected for subscriptions) opens up a lot of doors for very quick two way communication between web and mobile clients.

With GraphQL is it possible to replace the websocket used for subscription with a message-based approach (e.g. MQ)

Whereas the corporate environment I am working in accepts the use of http(s) based request response patterns, which is OK for GraphQL Query and Mutation, they have issues with the use of websockets as needed for GraphQL Subscription and would prefer that the subscription is routed via IBM MQ.
Does anyone have any experience with this? I am thinking of using Apollo Server to serve up the GraphQL interface. Perhaps there is a front-end subscription solution that can be plugged in using IBM MQ? The back end data sources are Oracle databases.
Message queues are usually used to communicate between services while web sockets are how browsers can communicate with the server over a constant socket. This allows the server to send data to the client when a new event of a subscription arrived (classically browsers only supported "pull" and could only receive data when they asked for it). Browsers don't implement the MQ protocols you would need to directly subscribe to the MQ itself. I am not an expert on MQs but what is usually done is there is a subscription server that connects to the client via web socket. The subscription service then itself subscribes to the message queue and notifies relevant clients about their subscribed events. You can easily scale the subscription servers horizontally when you need additional resources.

Will each Graphql Subscription from same browser create one websocket connection?

I know what is graphql subscription.
My question is if each subscription will create one websocket connection?
Or all the subscription from each browser is combined to one websocket connection?
I couldn't find answer anywhere in document.
GraphQL itself purposefully does not specify a transport layer in the specification. Therfore the answer depends on the implementation that you are using but for the implementations it makes sense to have only one connection. In Apollo you can use apollo-link-ws to connect to the server. This link then creates (an keeps alive) a single socket to the server using subscriptions-transport-ws. It can also handle all GraphQL methods (not only subscriptions) using the web socket.

The theory of websockets with API

I have an API running on a server, which handle users connection and a messaging system.
Beside that, I launched a websocket on that same server, waiting for connections and stuff.
And let's say we can get access to this by an Android app.
I'm having troubles to figure out what I should do now, here are my thoughts:
1 - When a user connect to the app, the API connect to the websocket. We allow the Android app only to listen on this socket to get new messages. When the user want to answer, the Android app send a message to the API. The API writes itself the received message to the socket, which will be read back by the Android app used by another user.
This way, the API can store the message in database before writing it in the socket.
2- The API does not connect to the websocket in any way. The Android app listen and write to the websocket when needed, and should, when writing to the websocket, also send a request to the API so it can store the message in DB.
May be none of the above is correct, please let me know
EDIT
I already understood why I should use a websocket, seems like it's the best way to have this "real time" system (when getting a new message for example) instead of forcing the client to make an HTTP request every x seconds to check if there are new messages.
What I still don't understand, is how it is suppose to communicate with my database. Sorry if my example is not clear, but I'll try to keep going with it :
My messaging system need to store all messages in my API database, to have some kind of historic of the conversation.
But it seems like a websocket must be running separately from the API, I mean it's another program right? Because it's not for HTTP requests
So should the API also listen to this websocket to catch new messages and store them?
You really have not described what the requirements are for your application so it's hard for us to directly advise what your app should do. You really shouldn't start out your analysis by saying that you have a webSocket and you're trying to figure out what to do with it. Instead, lay out the requirements of your app and figure out what technology will best meet those requirements.
Since your requirements are not clear, I'll talk about what a webSocket is best used for and what more traditional http requests are best used for.
Here are some characteristics of a webSocket:
It's designed to be continuously connected over some longer duration of time (much longer than the duration of one exchange between client and server).
The connection is typically made from a client to a server.
Once the connection is established, then data can be sent in either direction from client to server or from server to client at any time. This is a huge difference from a typical http request where data can only be requested by the client - with an http request the server can not initiate the sending of data to the client.
A webSocket is not a request/response architecture by default. In fact to make it work like request/response requires building a layer on top of the webSocket protocol so you can tell which response goes with which request. http is natively request/response.
Because a webSocket is designed to be continuously connected (or at least connected for some duration of time), it works very well (and with lower overhead) for situations where there is frequent communication between the two endpoints. The connection is already established and data can just be sent without any connection establishment overhead. In addition, the overhead per message is typically smaller with a webSocket than with http.
So, here are a couple typical reasons why you might choose one over the other.
If you need to be able to send data from server to client without having the client regular poll for new data, then a webSocket is very well designed for that and http cannot do that.
If you are frequently sending lots of small bits of data (for example, a temperature probe sending the current temperature every 10 seconds), then a webSocket will incur less network and server overhead than initiating a new http request for every new piece of data.
If you don't have either of the above situations, then you may not have any real need for a webSocket and an http request/response model may just be simpler.
If you really need request/response where a specific response is tied to a specific request, then that is built into http and is not a built-in feature of webSockets.
You may also find these other posts useful:
What are the pitfalls of using Websockets in place of RESTful HTTP?
What's the difference between WebSocket and plain socket communication?
Push notification | is websocket mandatory?
How does WebSockets server architecture work?
Response to Your Edit
But it seems like a websocket must be running separately from the API,
I mean it's another program right? Because it's not for HTTP requests
The same process that supports your API can also be serving the webSocket connections. Thus, when you get incoming data on the webSocket, you can just write it directly to the database the same way the API would access the database. So, NO the webSocket server does not have to be a separate program or process.
So should the API also listen to this websocket to catch new messages
and store them?
No, I don't think so. Only one process can be listening to a set of incoming webSocket connections.

Resources