From cd811195f1ea11290e2c30798f19d0847447877f Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Wed, 23 Feb 2022 20:02:37 +0300 Subject: [PATCH] feat: added history limit to messages store --- CHANGELOG.md | 1 + app/Services/WsService.ts | 7 ++++--- app/Store/MessageStore.ts | 8 ++++++++ app/Store/NotificationStore.ts | 26 ++++++++++++++------------ 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77c40e9..92aaab0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ## Added +- Saving latest notifications about new messages - Chat between users. (chat history). - About description for user and `last_login` column date - Updating info api route of authorized user diff --git a/app/Services/WsService.ts b/app/Services/WsService.ts index fb08d15..65fb100 100644 --- a/app/Services/WsService.ts +++ b/app/Services/WsService.ts @@ -31,7 +31,7 @@ export interface ServerToClientEvents { /** * Chat */ - 'chat:message': (data: { content: string; time: string; from: string; to: string }) => void; + 'chat:message': (data: { content: string; time: string; from: string; to: string; notificationId: string }) => void; } export interface ClientToServerEvents { @@ -129,8 +129,9 @@ class WsService { }; await this.messageStore.add(userId, to, message); - await this.notificationStore.add(to, `You received a new message.`); - this.io.to(to).emit('chat:message', message); + + const notification = await this.notificationStore.add(to, `You received a new private message`, 'MESSAGE'); + this.io.to(to).emit('chat:message', { ...message, notificationId: notification.id }); } }); diff --git a/app/Store/MessageStore.ts b/app/Store/MessageStore.ts index f289bdb..1403b0b 100644 --- a/app/Store/MessageStore.ts +++ b/app/Store/MessageStore.ts @@ -11,6 +11,7 @@ type MessageDataType = { }; const MESSAGE_TTL = 185 * 24 * 60 * 60; // 185 days +const MAX_MESSAGES_HISTORY = 100; class RedisMessageStore { public redisClient: RedisConnectionContract; @@ -37,8 +38,15 @@ class RedisMessageStore { .exec(); const convKey = this.createConversationKey(firstUserId, secondUserId); + const msgKeys = await this.redisClient.lrange(convKey, 0, -1); + await this.redisClient.lpush(convKey, msgKey); + if (msgKeys.length >= MAX_MESSAGES_HISTORY) { + const deletedMsgKey = await this.redisClient.rpop(convKey); + await this.redisClient.del(`message:${deletedMsgKey}`); + } + return 'OK'; } catch (error) { Logger.error(error); diff --git a/app/Store/NotificationStore.ts b/app/Store/NotificationStore.ts index 9009ac5..bd42094 100644 --- a/app/Store/NotificationStore.ts +++ b/app/Store/NotificationStore.ts @@ -5,6 +5,8 @@ import { nanoid } from 'nanoid'; const NOTIFICATION_TTL = 185 * 24 * 60 * 60; // 185 days type NotificationType = { + id: string; + type: 'SYSTEM' | 'MESSAGE'; content: string; time: string; }; @@ -16,25 +18,25 @@ class RedisNotificationStore { this.redisClient = redisClient; } - public async add(userId: string, message: string): Promise<'OK' | 'ERROR'> { + public async add(userId: string, content: string, type: NotificationType['type']): Promise { try { - const key = `notification:${nanoid()}`; + const id = nanoid(); + const key = `notification:${id}`; const timestamp = Date.now(); + const notification = { + id, + content, + time: new Date(timestamp).toISOString(), + type, + }; await this.redisClient.zadd(`user:${userId}`, timestamp, key); - await this.redisClient - .multi() - .hmset(key, { - content: message, - time: new Date(timestamp).toISOString(), - }) - .expire(key, NOTIFICATION_TTL) - .exec(); + await this.redisClient.multi().hmset(key, notification).expire(key, NOTIFICATION_TTL).exec(); - return 'OK'; + return notification; } catch (error) { Logger.error(error); - return 'ERROR'; + return Promise.reject(error); } }