resgateio / resgate

A Realtime API Gateway used with NATS to build REST, real time, and RPC APIs, where all your clients are synchronized seamlessly.
https://resgate.io
MIT License
685 stars 67 forks source link

Client connection tracking #155

Open jirenius opened 4 years ago

jirenius commented 4 years ago

Issue

Services want to be able to track which clients are currently connected to any of the Resgates.

Scope

This feature should consider the following:

  1. Resgate events on client connects/disconnects
  2. Handling of Resgate restart or Resgate disconnect from NATS server
  3. Handling of service restart or service disconnect from NATS server

Notes

The tracking of client connections should only be done for WebSocket connections, and not HTTP requests. The short-lived connection created for HTTP requests would only produce unnecessary traffic of limited use.

jirenius commented 4 years ago

Solution suggestion - Connection events

Scope consideration 1

Extending the RES protocol with two new events, published by Resgate:

Connection connect event

Subject
conn.<cid>.connect

Event sent by the gateways whenever a client has disconnected. The event payload has the following parameter:

gid
Gateway ID string that is unique to each gateway.

Example payload

{
  "gid": "resgate-12345"
}

Connection disconnect event

Subject
conn.<cid>.disconnect

Event sent by the gateways whenever a client connection is disconnected. The event payload has the following parameter:

gid
Gateway ID string that is unique to each gateway.

Example payload

{
  "gid": "resgate-12345"
}

Scope consideration 2

Adding two new system events for resgate start and stop, a service could act upon them by assuming all previously established connections for that Resgate instance are to be considered disconnected:

System start event

Subject
system.start

Event sent by the gateways on start up. The event payload has the following parameter:

gid
Gateway ID string that is unique to each gateway.

System stop event

Subject
system.stop

Event sent by the gateways on shutdown. The event payload has the following parameter:

gid
Gateway ID string that is unique to each gateway.

This would not cover the case when a Resgate failed to send the system.stop event on shutdown (due to crash or lost NATS connection), and is never restarted afterwards. This would leave the services unaware of any event.

Scope consideration 3

A system request, listened to by all gateways, would allow a restarted service to get a current list of connected clients from all resgate instances.

System connections (or status?) request

Subject
system.connections

Request listened to by all gateways.
The request has no payload.

Response Each gateway respond with a json object containing its Gateway ID (gid) and a list of current connection IDs (cid), including connection tokens:

{
  "gid": "resgate-12345",
  "connections": {
    "cid-1234": { "token": null },
    "cid-2345": { "token": { "userId": 42, "role": "guest" }}
  }
}
raphaelpereira commented 4 years ago

@jirenius why don't you add the token information on Scope consideration 1? That would make it easier for the application to identify which user is associated with the connection. Otherwise a explicit call to Scope 3 would be needed.

jirenius commented 4 years ago

@raphaelpereira

why don't you add the token information on Scope consideration 1

On connect, the token is always null. Resgate does not store state between reconnects, and has no concept of sessions. It is ResClient's task to rebuild state after a reconnect.

But you don't have to call "Scope3", but instead just listen for the conn.{cid}.token event, which is sent when the new connection gets its token.

On a disconnect/reconnect, this is what takes place: 1) ResClient is (involuntarily) disconnected

All above is done by ResClient automatically, so that the app doesn't have to bother.

raphaelpereira commented 3 years ago

@jirenius when will this be implemented?