Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client connection tracking #155

Open
jirenius opened this issue Apr 17, 2020 · 4 comments
Open

Client connection tracking #155

jirenius opened this issue Apr 17, 2020 · 4 comments
Labels
enhancement New feature or request

Comments

@jirenius
Copy link
Collaborator

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 jirenius added the enhancement New feature or request label Apr 17, 2020
@jirenius
Copy link
Collaborator Author

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
Copy link

@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
Copy link
Collaborator Author

jirenius commented Apr 23, 2020

@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
    • Resgate clears all state for that connection and will send a conn.{cid}.disconnect event.
  2. ResClient reconnects to the same, or a different Resgate
    • Resgate will send a conn.{cid}.connect event. No token is available for the new connection.
  3. ResClient sends an auth request from the ResClient.setOnConnect(() => { /... here .../ }) callback. The auth request contains credentials (maybe a jwt or some other refresh token) to reauthenticate. See Resgate.io - Client Session.
  4. The service handling the auth request sets a token for the new connection with a conn.{cid}.token event.
    • Any service keeping track on connections may listen for events sent in 4)
  5. ResClient resubscribes to previously subscribed resources and resynchronizes them locally.
  6. Resgate/ResClient state is restored!

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

@raphaelpereira
Copy link

@jirenius when will this be implemented?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants