Managing client connections
The Squid Backend SDK offers functionality that enables the backend to detect client connections to the server in real-time.
This feature allows you to monitor and manage the connectivity of clients to your Squid backend, giving you the power to:
- Gain real-time information about client connections and disconnections
- Understand client connections by leveraging unique client IDs
- Perform specific actions based on connectivity status
Handling client connections
Squid provides a decorator which can be used to handle a change in a client's connection status. This is achieved by decorating a
function with the @clientConnectionStateHandler
decorator within a class that extends the base SquidService
class. Within
this decorator, you can add your business logic to execute the desired behavior.
The @clientConnectionStateHandler
decorator takes two parameters:
- The
ClientId
that initiated the Squid Client SDK, accepted as a string. - The
ClientConnectionState
that contains the client's current connection status. This can be one of three values:CONNECTED
indicates that the client just connectedDISCONNECTED
indicates that the client just disconnectedREMOVED
indicates that the client has disconnected and Squid removed theirClientId
. This means that the next time the client connects, they will have a newClientId
Understanding the client connection process
There are a few key steps in the process of utilizing each client's connection to the Squid server:
- Whenever a client initially connects, Squid assigns it a unique
clientId
- Once a user is authenticated, we can link their
userId
with the correspondingclientId
in order to track each user's online status - When a client joins a chatroom, we can insert into a user presence collection and store which
clientIds
and associateduserIds
are present in the chatroom - We can detect when a client disconnects using the
@clientConnectionStateHandler
decorator and update the corresponding user's status to offline - We can detect when a client is removed using the
@clientConnectionStateHandler
decorator and delete the corresponding user from the user presence collection
Providing each client a unique clientId
upon connection enables precise tracking and management of individual users' statuses.
This feature allows for the association of userIds
with their respective clientIds
, facilitating real-time monitoring of client presence.
Connection status on the client
To utilize this flow on the client, Squid provides the following options:
squid.connectionDetails().connected
: returns a boolean of whether the client is currently connected to the serversquid.connectionDetails().observeConnected()
: returns an observable that emits true when the client is connected to the server and false when the client is disconnected from the serversquid.connectionDetails().clientId
: returns theclientId
that is assigned to the current client
Connection status on the backend
To utilize this flow on the backend, Squid provides the following options:
- The
@clientConnectionStateHandler
decorator, as described above this.context.clientId
: returns the id of the client that initiated this request
Chatroom example
The following is a basic example of how to manage this process in a chat application. Using the @clientConnectionStateHandler
decorator, the client
could get a list of all users that are present in a chatroom and their corresponding statuses (i.e. whether they are online or offline).
Because we can tell which clientIds
are connected (but not which userIds
), we need to to link each connection's clientId
to the corresponding userId
in order to track each user's online status.
To do so, we can mutate the presence collection whenever a user joins the chatroom. The collection will contain the clientIds
as document IDs, and the data inserted is the userId
and their status (which will be online
because we are executing the function whenever a user joins).
We can update the collection whenever a user establishes a new connection. The observeConnected()
function (which returns true when the client is connected to the server) triggers the mutation once the connection is established:
type PresenceData = {
userId: string;
status: 'online' | 'offline';
};
...
squid.connectionDetails().observeConnected().pipe(
filter(Boolean)
).subscribe(() =>
squid
.collection<PresenceData>('userPresence')
.doc(squid.connectionDetails().clientId)
.insert({ userId, status: 'online' }).then(); // get userId from auth provider
)
Executing this mutation links clientIds
to userIds
in order to initialize users' online status.
To read more about Squid and authentication, read our documentation on integrating Squid with authentication providers.
The next step is to monitor users' offline status. This is where the @clientConnectionStateHandler
decorator is essential.
A clientId
becoming DISCONNECTED
represents a user logging off the chatroom. Therefore, we need to update the user's status
to offline. Additionally, a clientId
becoming REMOVED
represents a user leaving the chatroom:
import { SquidService, clientConnectionStateHandler } from '@squidcloud/backend';
import { ClientConnectionState, ClientId } from '@squidcloud/client';
export class ExampleService extends SquidService {
...
@clientConnectionStateHandler()
async handleClientConnectionStateChange(
clientId: ClientId,
connectionState: ClientConnectionState
): Promise<void> {
if (connectionState === 'DISCONNECTED') { // user logged off
await this.squid
.collection('userPresence')
.doc(clientId)
.update({ status: 'offline' });
} else if (connectionState === 'REMOVED') { // user left the chat
await this.squid
.collection('userPresence')
.doc(clientId)
.delete();
}
}
}
The client can then query the userPresence
collection in order to get a list of users in the chatroom and their statuses.
Below is an example of this process working in real time using Squid + React. This is a basic sample project which treats each
tab (clientId
) as a new authenticated user:
By understanding how to monitor and react to client connections in Squid, you can manage those connectivity changes more effectively for your use case.