appwrite / sdk-for-web

[READ-ONLY] Official Appwrite Web SDK ๐Ÿงก
https://appwrite.io
BSD 3-Clause "New" or "Revised" License
273 stars 59 forks source link

๐Ÿš€ Feature: Websocket Connect and Disconnect Events #40

Open Towerful opened 1 year ago

Towerful commented 1 year ago

๐Ÿ”– Feature description

Have the Client.Realtime emit events when the websocket connects and disconnects

๐ŸŽค Pitch

Currently there is no way to detect this.
If the websocket disconnects and you are relying on the realtime connection to track data between the client and the database, you will miss CRUD events, and your client data may not reflect the database data.
With events indicating WSS connect and disconnect, this would allow feedback to the user that it is no longer realtime, and to do a full data refetch/refresh when the websocket connects.

๐Ÿ‘€ Have you spent some time to check if this issue has been raised before?

๐Ÿข Have you read the Code of Conduct?

stnguyen90 commented 1 year ago

@Towerful, thanks for creating this issue! ๐Ÿ™ Is this a duplicate of https://github.com/appwrite/appwrite/issues/2418? If so, can this be closed?

Towerful commented 1 year ago

I don't think it is, perhaps I didn't explain myself well.
However I didn't check appwrite/appwrite for duplicates.

I feel like that https://github.com/appwrite/appwrite/issues/2418 is a server side feature. When a client disconnecting would trigger a function on the server, in order to track some sort of presence.

I would be looking for client side events regarding the websocket connection status.
I don't believe there is any "event replay" from the server to tell the client the events it missed while the client was disconnected.
So if I have local state on the client, and I am relying on the websocket to modify that local state according to the create/update/delete events in order to reflect the actual data on the server, the clients local state will no longer be in sync with the server data due to the events it missed when the websocket was disconnected.
The user may not realise that they have stale data, as they will still get further updates. But the existing client state will likely still be stale, as they have missed the chain of events between the disconnect and the reconnect.

Having a 'socket disconnected' event raised would allow me to tell the user the client has disconnected.
Having a 'socket reconnecting' event would allow me to tell the user the client is trying to reconnect, and what attempt number it is.
Having a 'socket connected' event would allow me to re-run all my database queries to fetch fresh data, so the client can then track the server data correctly.

I hope that makes sense.

The events could be implemented as an event, for example:

{
    events: ['realtime.disconnected'];
    channels: string[];
    timestamp: number;
    payload: { };
}

{
    events: ['realtime.reconnecting'];
    channels: string[];
    timestamp: number;
    payload: { 
        attempt: number,
        timeout: number
    };
}

{
    events: ['realtime.connected'];
    channels: string[];
    timestamp: number;
    payload: { };
}

which could be raised for all subscribed callbacks.

I don't think this would be a breaking change, as implementations normally rely on events.includes('databases.*.collections.*.documents.update') to test if an event is relevant.
As these websocket events would be namespaced under realtime, this shouldn't break existing functionality.

SaabirMohamed commented 3 months ago

I have had the same issue and sorted it eventually. my app relies heavily on realtime for chat and interactivity I cant have it disconnect like that. note: Appwrite's default behaviour with the traefek proxy directly works perfectly

basically with NGINX (default disconnect after 60 seconds so) there are settings online to allow and handle this disconnects apparently...in my testing i still disconnect. (may i did itwrong)

cloudflare ...also disconnects after 100 seconds. (according to support)

My Solutions: solution 1 (if you forced to proxy or some fw)...there is an onDone() event you can consume and just re-listen to stream or use a timer to re-connect in 99 seconds (this is not nice)

solution 2 (in cloudflare click dns only -- unselect proxied) and the problem goes away. with the above ...you will still have a ssl cert ..or add yours. cloudflare is awesome ...and all appwrite things worked perfect except realtime. ..also in cloudfare you could just create tunnel directly onto that server ( I haven't tested this) but you in the tunnel...

F.Y.I in dart (if you use the default Stream builder (it has onError, onData)...so it wont work you need the onDone which is in the appwrite class...that one luckily does get triggered (onError, onData wont, no idea why..its like they silently disconnect) this drove me crazy ... so the proxies seem to close with noError noData but with "Im Done" holding this connection)

xuelink commented 3 months ago

i think it shou

I have had the same issue and sorted it eventually. my app relies heavily on realtime for chat and interactivity I cant have it disconnect like that. note: Appwrite's default behaviour with the traefek proxy directly works perfectly

basically with NGINX (default disconnect after 60 seconds so) there are settings online to allow and handle this disconnects apparently...in my testing i still disconnect. (may i did itwrong)

cloudflare ...also disconnects after 100 seconds. (according to support)

My Solutions: solution 1 (if you forced to proxy or some fw)...there is an onDone() event you can consume and just re-listen to stream or use a timer to re-connect in 99 seconds (this is not nice)

solution 2 (in cloudflare click dns only -- unselect proxied) and the problem goes away. with the above ...you will still have a ssl cert ..or add yours. cloudflare is awesome ...and all appwrite things worked perfect except realtime. ..also in cloudfare you could just create tunnel directly onto that server ( I haven't tested this) but you in the tunnel...

F.Y.I in dart (if you use the default Stream builder (it has onError, onData)...so it wont work you need the onDone which is in the appwrite class...that one luckily does get triggered (onError, onData wont, no idea why..its like they silently disconnect) this drove me crazy ... so the proxies seem to close with noError noData but with "Im Done" holding this connection)

this is exactly what i am thinking about, in sdk for dart there are events for onDone and onError but in sdk-for-web doesnt here

Screenshot 2024-03-08 at 3 34 21โ€ฏPM