refactor: moved some logic to online controller for websocket server

This commit is contained in:
Sergey Yarkov 2022-01-31 00:03:48 +03:00
parent 13d75468d9
commit d46c2bb138
2 changed files with 81 additions and 47 deletions

View File

@ -1,24 +1,92 @@
import Ws, { ClientToServerEvents, InterServerEvents, ServerToClientEvents, SocketData } from 'App/Services/WsService'; import { Server, Socket } from 'socket.io';
import { Socket } from 'socket.io'; import { ClientToServerEvents, InterServerEvents, ServerToClientEvents, SocketData } from 'App/Services/WsService';
import InMemorySessionStore from 'App/Store/SessionStore'; import RedisSessionStore from 'App/Store/SessionStore';
import Logger from '@ioc:Adonis/Core/Logger';
export default class OnlineController { export default class OnlineController {
public socket: Socket<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>; public socket: Socket<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>;
constructor(socket: Socket) { public io: Server<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>;
public sessionStore: RedisSessionStore;
constructor(
socket: Socket,
io: Server<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>,
sessionStore: RedisSessionStore
) {
this.socket = socket; this.socket = socket;
this.onConnected(); this.io = io;
this.onDisconnected(); this.sessionStore = sessionStore;
this.onConnected(socket);
this.socket.on('disconnect', reason => this.onDisconnected(reason));
}
public sendOnlineCount(online: number) {
this.socket.emit('user:online', online);
this.socket.broadcast.emit('user:online', online);
}
public setUserOnline() {
const { sessionId, userId, userName } = this.socket.data;
if (sessionId && userId && userName) {
/**
* Set session and send online count
*/
this.sessionStore
.saveSession(sessionId, { userId, userName, connected: true })
.then(() => this.sessionStore.getOnlineSessionsCount())
.then(online => this.sendOnlineCount(online));
}
}
public async setUserOffline() {
if (this.socket.data.userName && this.socket.data.sessionId && this.socket.data.userId) {
const matchingSockets = await this.io.in(this.socket.data.userId).allSockets();
const isDisconnected = matchingSockets.size === 0;
if (isDisconnected) {
const { sessionId, userId, userName } = this.socket.data;
/**
* Update connection flag of socket to flase and send online count
*/
this.sessionStore
.saveSession(sessionId, { userId, userName, connected: false })
.then(() => this.sessionStore.getOnlineSessionsCount())
.then(online => this.socket.broadcast.emit('user:online', online));
}
}
} }
/** /**
* On socket connected * On socket connected
*/ */
public async onConnected() {} public async onConnected(socket: Socket<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>) {
/**
* Set user online on connected
*/
this.setUserOnline();
/**
* Broadcast to all clients about new connection
*/
if (this.socket.data.userName && this.socket.data.sessionId && this.socket.data.userId) {
socket.broadcast.emit('user:connected', { userId: this.socket.data.userId, userName: this.socket.data.userName });
}
/**
* Watch status of user and set session
*/
socket.on('user:status', () => this.setUserOnline());
}
/** /**
* On socket disconnected * On socket disconnected
*/ */
public async onDisconnected() {} // eslint-disable-next-line @typescript-eslint/no-unused-vars
public onDisconnected(_reason: string) {
this.setUserOffline();
}
} }

View File

@ -18,7 +18,7 @@ export interface ServerToClientEvents {
* User * User
*/ */
'user:session': (data: { sessionId: string | undefined; userId: string | undefined }) => void; 'user:session': (data: { sessionId: string | undefined; userId: string | undefined }) => void;
'user:connected': (data: { userId: string; socketId: string }) => void; 'user:connected': (data: { userId: string; userName: string }) => void;
'user:online': (data: number) => void; 'user:online': (data: number) => void;
} }
@ -27,6 +27,7 @@ export interface ClientToServerEvents {
* User * User
*/ */
'user:logout': () => void; 'user:logout': () => void;
'user:status': () => void;
} }
export interface InterServerEvents {} export interface InterServerEvents {}
@ -65,23 +66,11 @@ class WsService {
private listen() { private listen() {
this.io.on('connection', socket => { this.io.on('connection', socket => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const onlineController = new OnlineController(socket); const onlineController = new OnlineController(socket, this.io, this.sessionStore);
const { sessionId, userId, userName } = socket.data; const { sessionId, userId, userName } = socket.data;
const isExistSocketData = !!(sessionId && userId && userName); const isExistSocketData = !!(sessionId && userId && userName);
/**
* Set user session and send online count
*/
if (isExistSocketData) {
this.sessionStore
.saveSession(sessionId, { userId, userName, connected: true })
.then(() => this.sessionStore.getOnlineSessionsCount())
.then(online => {
socket.emit('user:online', online);
socket.broadcast.emit('user:online', online);
});
}
/** /**
* Send session to client * Send session to client
*/ */
@ -95,29 +84,6 @@ class WsService {
await this.sessionStore.destroySession(sessionId); await this.sessionStore.destroySession(sessionId);
} }
}); });
/**
* Broadcast to all clients about new connection
*/
socket.broadcast.emit('user:connected', {
userId: socket.handshake.auth.userId,
socketId: socket.id,
});
socket.on('disconnect', async () => {
if (isExistSocketData) {
const matchingSockets = await this.io.in(userId).allSockets();
const isDisconnected = matchingSockets.size === 0;
if (isDisconnected) {
/**
* Update connection flag of socket to flase and send online count
*/
this.sessionStore.saveSession(sessionId, { userId, userName, connected: false });
this.sessionStore.getOnlineSessionsCount().then(online => socket.broadcast.emit('user:online', online));
}
}
});
}); });
} }