graphql-engine icon indicating copy to clipboard operation
graphql-engine copied to clipboard

Hook / event that we can subscribe on when websocket connected / disconnected

Open michaelhayman opened this issue 5 years ago • 6 comments

I see this commonly mentioned on the hasura channel but I couldn't find an issue for it.

Would be really great to be able to trigger some kind of function when this happens - e.g. update the user record to update online status / last online, rather than mutating constantly from the client side which doesn't seem very efficient.

This is straightforward to implement when running your own websockets server, but is a bit painful with Hasura, since it has to be done from client side. We can watch websockets status from client, but if the browser crashes we get no close event, so the user stays perpetually online.

❤️

michaelhayman avatar Oct 17 '19 12:10 michaelhayman

Some ideas for the implementation:

  1. Provide an admin only ws endpoint on which all graphql-ws related events (opened/closed with session variables) are published. This seemed like a neat idea but when you horizontally scale graphql-engine, things are not as seamless because now you'll need to subscribe to all the instances as they go up and down, which definitely is not easy.
  2. Call a user provided webhook on graphql-ws events, this doesn't suffer from the previous problem but has a few of its own, we'll need to guarantee ordered delivery of events which becomes tricky if we allow some sort of a retry mechanism. Everytime the server needs to close all ws connections (say the schema changed), it'll need to make n(open connections) number of webhook calls and wait for all of them to finish.
  3. Write the events to a user specified Postgres table: ordering can be easily guaranteed, inserting several events at once is also not a problem. More importantly, writing logic for the use case in this feature request is extremely trivial with Postgres triggers on this table. I like this the most, because a) it is trivial to implement and b) having this data in Postgres opens up a lot of opportunities, you can pipe these to say external sources like kafka, or use hasura's event triggers etc. The only downside that I can think of is that this has to go through Postgres.

0x777 avatar Oct 28 '19 11:10 0x777

I think too this is necessary, I'm in a case that I need to save who is online and who is disconnected to subscriptions. A workaround that I'm implementing is a secondary websockets with a AWS Lambda to manage only the currently state of the user, I can't see other workaround now...

BlueSeph28 avatar Dec 05 '19 18:12 BlueSeph28

We also need this feature, our use case is the same, for user presence. The idea we had is to just be able to define a mutation to be triggered on ws connect, provided this mutation has access to hasura auth headers eg. x-hasure-user-id. The suggestion with a webhook triggered on these events works very nice also.

AvronNet avatar Feb 16 '20 21:02 AvronNet

Write the events to a user specified Postgres table: ordering can be easily guaranteed, inserting several events at once is also not a problem. More importantly, writing logic for the use case in this feature request is extremely trivial with Postgres triggers on this table. I like this the most, because a) it is trivial to implement and b) having this data in Postgres opens up a lot of opportunities, you can pipe these to say external sources like kafka, or use hasura's event triggers etc. The only downside that I can think of is that this has to go through Postgres.

@0x777 I agree with your 3rd idea for implementation. If there's a way for it to all utilize Hasura's existing event triggers by doing it through postgres, I think that would work well.

For my purposes, the main thing I need is some way to identify which user connected/disconnected when the event is triggered. So I think that as long as the headers (including x-hasura-user-id) used to create the ws connection are available in the triggered event handler, this solution would work well.

amille14 avatar Aug 26 '20 15:08 amille14

I am in need of a similar use case. We need to track in the backend when websockets are connected or disconnected, when subscriptions are created or stopped, when data is sent over subscriptions etc. We also need the ability to tie an external subscription query Id to the subscription Id. (we track the search queries that the users create for reporting purposes and driving other business needs). I am looking forward to these events exposed on the Hasura API, so that we do reporting on it. I know Hasura Pro has the monitoring capabilities though timescaleDB that we could look into. But that is a lot of logging data to parse through in addition to specific events and data that we are trying to collect.

vaibhavpingle avatar Jan 21 '21 16:01 vaibhavpingle

Have there been any plans on implementing this?

We would very much like to know when someone unsubscribes from something. Our use case is to allow only one user to edit a record at a time and we would like to reset the state if they close their browser. Yes this could be solved by periodically writing a timestamp, but that becomes computationally expensive at a large scale.

davidpanic avatar Sep 19 '22 13:09 davidpanic

hasura can use phoenix/elixir for creating channel and presence websocket server.

sina68 avatar Dec 09 '22 13:12 sina68

a solution for now, is using webhook auth and save websocket connections in redis and use cache header if user not back in interval time redis can trigger and you know user is disconnected. or update user last seen on every websocket token auth.

sina68 avatar Dec 09 '22 13:12 sina68

Just keeping this issue alive, as it would be a great feature to have. We're going to have to spin up a separate server just to track these events.

That said it doesn't seem like there has been much progress here, are there any pointers for someone who may want to take a stab at tackling this feature?

camilobern avatar Feb 28 '23 12:02 camilobern

Voicing support for this as well. As a quick solution, we've been spinning up a Firebase Realtime Database instance just to achieve this (Firebase has a mechanism that allows defining an onDisconnect event that will modify or clean up data when the user socket disconnects -- straight from their side). But it's really inconvenient to use and requires an entirely separate setup to track. Would love to get this out of the box with Hasura.

https://firebase.google.com/docs/reference/js/v8/firebase.database.OnDisconnect

itsmingjie avatar Feb 28 '23 16:02 itsmingjie