Real-time Editor Gateway
Relevant source files
The following files were used as context for generating this wiki page:
The Real-time Editor Gateway is a WebSocket-based communication system designed to enable real-time collaboration features within the Ever-Rec image editor. It is built using NestJS's WebSocket module on the server-side and socket.io-client on the client-side.
The primary purpose of this gateway is to broadcast updates to all clients currently viewing and editing the same image. As of the current implementation, its main function is to synchronize marker data, ensuring that when one user adds, modifies, or deletes a marker, the changes are reflected instantly for all other collaborators.
Architecture Overview
The system consists of a server-side gateway and a client-side listener. The server-side component, EditorGateway, is responsible for managing WebSocket connections and broadcasting events. The client-side component, located within the editor page, establishes a connection to the gateway and listens for specific events to update the UI in real-time.
The following diagram illustrates the high-level architecture of the real-time update flow.
Server-Side Implementation
The server-side logic is encapsulated within the EditorGateway class, which is a NestJS WebSocket gateway.
Sources: apps/api/src/module/editor-websocket-module/editor.gateway.ts, apps/api/src/module/editor-websocket-module/editor-websocket.module.ts
Core Components
@WebSocketGateway(): This decorator marks theEditorGatewayclass as a WebSocket provider. It is configured with CORS settings to allow connections from any origin.@WebSocketServer(): This decorator provides access to the nativesocket.ioserver instance, which is used to broadcast messages to clients.OnGatewayInit,OnGatewayConnection,OnGatewayDisconnect: These interfaces are implemented to hook into the lifecycle of the gateway, allowing for logging and handling of client connections and disconnections.
The diagram below shows the structure of the EditorGateway class.
Event Broadcasting
The key method in the gateway is emitMarkersUpdate. This function is called from other services (e.g., when markers are updated via a REST API call) to propagate changes to all connected clients.
// File: apps/api/src/module/editor-websocket-module/editor.gateway.ts:38-42
public emitMarkersUpdate(payload: { markers: string; uid: string }) {
this.server.emit('markers-updated', payload);
}
This method emits a markers-updated event with a payload containing the updated marker data (as a JSON string) and the unique ID of the user who initiated the change.
Client-Side Integration
The client-side integration is handled within the EditorScreen component. It uses the socket.io-client library to connect to the WebSocket server and handle incoming events.
Sources: apps/portal/pages/edit/[id].tsx
Connection and Event Handling
A useEffect hook establishes the WebSocket connection when the component mounts and disconnects when it unmounts. It listens for the markers-updated event and updates the component's state with the new marker data.
A crucial part of the logic is to ignore events triggered by the current user to prevent an update loop. This is achieved by comparing the uid in the event payload with the current user's ID.
// File: apps/portal/pages/edit/[id].tsx:1020-1033
useEffect(() => {
// Connect to your server
const socket = io(process.env.NEXT_PUBLIC_API_BASE_URL || '', {
transports: ['websocket'],
});
// Listen for 'connect' event
socket.on('connect', () => {
console.info('Successfully connected to the websocket');
});
// Listen for 'markers-updated' event
socket.on('markers-updated', (data) => {
console.log(data);
if (data?.uid !== user?.id) {
data.markers && setMarkers(JSON.parse(data.markers));
}
});
// Cleanup the effect (disconnect) when the component is unmounted.
return () => {
socket.disconnect();
};
}, [user]);
Real-time Update Sequence
The following sequence diagram details the end-to-end flow of a real-time marker update.
WebSocket Events
The gateway currently handles one primary custom event for real-time collaboration.
| Event Name | Payload | Direction | Description |
|---|---|---|---|
connect | - | Client -> Server | A client establishes a connection to the WebSocket server. |
disconnect | - | Client -> Server | A client disconnects from the WebSocket server. |
markers-updated | { markers: string, uid: string } | Server -> Client | Broadcasts updated marker data to all connected clients. The uid identifies the user who made the change. |
Sources: apps/api/src/module/editor-websocket-module/editor.gateway.ts:28-42, apps/portal/pages/edit/[id].tsx:1026-1031
Dependencies
The real-time functionality relies on the following key packages:
| Package | Application | Usage |
|---|---|---|
@nestjs/websockets | api | Core NestJS module for WebSocket support. |
@nestjs/platform-socket.io | api | socket.io adapter for NestJS. |
socket.io | api | The underlying WebSocket server library. |
socket.io-client | portal | The client-side library for connecting to the WebSocket server. |
Sources: apps/api/package.json:44-45, apps/portal/package.json:61
Summary
The Real-time Editor Gateway is a foundational component for collaborative features in the Ever-Rec editor. By leveraging WebSockets, it provides a low-latency communication channel to synchronize state between multiple users. The current implementation is focused on updating markers, but the architecture is extensible and can be adapted to support other real-time features in the future by adding new event handlers and emitters.