diff --git a/app/Controllers/Ws/OnlineController.ts b/app/Controllers/Ws/OnlineController.ts index d4a796b..9f59b86 100644 --- a/app/Controllers/Ws/OnlineController.ts +++ b/app/Controllers/Ws/OnlineController.ts @@ -1,24 +1,92 @@ -import Ws, { ClientToServerEvents, InterServerEvents, ServerToClientEvents, SocketData } from 'App/Services/WsService'; -import { Socket } from 'socket.io'; -import InMemorySessionStore from 'App/Store/SessionStore'; -import Logger from '@ioc:Adonis/Core/Logger'; +import { Server, Socket } from 'socket.io'; +import { ClientToServerEvents, InterServerEvents, ServerToClientEvents, SocketData } from 'App/Services/WsService'; +import RedisSessionStore from 'App/Store/SessionStore'; export default class OnlineController { public socket: Socket; - constructor(socket: Socket) { + public io: Server; + + public sessionStore: RedisSessionStore; + + constructor( + socket: Socket, + io: Server, + sessionStore: RedisSessionStore + ) { this.socket = socket; - this.onConnected(); - this.onDisconnected(); + this.io = io; + 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 */ - public async onConnected() {} + public async onConnected(socket: Socket) { + /** + * 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 */ - public async onDisconnected() {} + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public onDisconnected(_reason: string) { + this.setUserOffline(); + } } diff --git a/app/Services/WsService.ts b/app/Services/WsService.ts index 33b923e..2cc313f 100644 --- a/app/Services/WsService.ts +++ b/app/Services/WsService.ts @@ -18,7 +18,7 @@ export interface ServerToClientEvents { * User */ '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; } @@ -27,6 +27,7 @@ export interface ClientToServerEvents { * User */ 'user:logout': () => void; + 'user:status': () => void; } export interface InterServerEvents {} @@ -65,23 +66,11 @@ class WsService { private listen() { this.io.on('connection', socket => { // 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 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 */ @@ -95,29 +84,6 @@ class WsService { 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)); - } - } - }); }); }