## Description
Currently, the only reliable way to track a session in R11s is via
Deli's `SessionResult` metric, which depends on Join/Leave Ops and
Deli's "close" handler. This session tracking does not account for
sessions that only have Reader clients with no Ops.
This PR introduces an optional, alternative method for tracking
collaboration sessions within the Nexus lambda itself, which is able to
account for Read-only sessions.
> **Note:** This is an alternative to #9191 which requires creating
Orderer connections to manage read clients using Deli, as well as
keep-alive pings from the frontend (Nexus in our case). We do not want
to spin up Deli and create Orderer connections for read sessions.
### Solution Design Details
> **Context** The original design attempted to only use information
already available from `IClientManager` to understand active session
information and act accordingly. However, the "currently connected
client list" available via `IClientManager` was insufficient for
handling various multi-instance scenarios such as clients leaving from
separate Nexus instances causing the session to "terminate" too
quickly/twice or a Nexus instance shutting down causing a session end
timer to be lost.
1. **"Session Creation (First Client Join)"**: When a client for a given
document connects to the socket server while no other clients are
connected/active for that document, and the previous session either
never existed or was inactive for more than 10 minutes, the session is
"created/started."
2. **"Session Expansion/Continuation (Client Join):** When a client for
a given document connects to the socket server while other clients are
connected/active for that document, or the previous session has been
inactive for less than 10 minutes, the session is updated with
information about that new client, and any existing timers are reset.
3. **Session End (Last Client Leave):** When the only remaining
connected client for a given document disconnects from the socket
server, the session is updated with "last client leave time" and a 10
minute timeout is started.
4. **Session Timeout (Inactive for 10 minutes):** When a session's
inactivity timer expires and there are still no clients in the session
according to the ClientManager, the session is logged as "ended" and
cleaned up.
All of the above "session" information is stored within a Redis HashMap
that allows the list of current sessions to be retrieved and iterated
over, or a single session to be retrieved and updated.
## Breaking Changes
### Firm Input Validation
When the client sends a malformed connect message (i.e. the message does
not contain all expected properties with expected types), Nexus will
emit a `connect_document_error` message with a 400 error code,
indicating malformed user input to the client.
#### Context
Nexus currently makes a lot of type assumptions about the client's
`IConnect` message in the `connect_document` event handler. This can
cause the service to crash due to unhandled TypeErrors at runtime. This
PR introduces strong type checks for the incoming `IConnect` message and
its internal `IClient` details so that Nexus can safely access the
expected properties in that message.
## Reviewer Guidance
- **Main Session Tracking Logic**: server/r11s/packages/services/src
`redisSessionManager.ts` and `sessionTracker.ts`
- **Main Nexus Session Tracking**:
server/r11s/packages/lambdas/src/nexus `connect.ts` and `disconnect.ts`
- There is also a small refactor in `disconnect.ts` to make the
Disconnect handler structure more similar to the Connect handler by
moving the internal loops into their own named functions.
- **Type Validation**: server/r11s/packages/lambdas/src/nexus `index.ts`
and `protocol.ts`
---------
Co-authored-by: Tyler Butler <tyler@tylerbutler.com>