feat: added history limit to messages store

This commit is contained in:
Sergey Yarkov 2022-02-23 20:02:37 +03:00
parent 877e15bcde
commit cd811195f1
4 changed files with 27 additions and 15 deletions

View File

@ -8,6 +8,7 @@
## Added ## Added
- Saving latest notifications about new messages
- Chat between users. (chat history). - Chat between users. (chat history).
- About description for user and `last_login` column date - About description for user and `last_login` column date
- Updating info api route of authorized user - Updating info api route of authorized user

View File

@ -31,7 +31,7 @@ export interface ServerToClientEvents {
/** /**
* Chat * 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 { export interface ClientToServerEvents {
@ -129,8 +129,9 @@ class WsService {
}; };
await this.messageStore.add(userId, to, message); 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 });
} }
}); });

View File

@ -11,6 +11,7 @@ type MessageDataType = {
}; };
const MESSAGE_TTL = 185 * 24 * 60 * 60; // 185 days const MESSAGE_TTL = 185 * 24 * 60 * 60; // 185 days
const MAX_MESSAGES_HISTORY = 100;
class RedisMessageStore { class RedisMessageStore {
public redisClient: RedisConnectionContract; public redisClient: RedisConnectionContract;
@ -37,8 +38,15 @@ class RedisMessageStore {
.exec(); .exec();
const convKey = this.createConversationKey(firstUserId, secondUserId); const convKey = this.createConversationKey(firstUserId, secondUserId);
const msgKeys = await this.redisClient.lrange(convKey, 0, -1);
await this.redisClient.lpush(convKey, msgKey); 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'; return 'OK';
} catch (error) { } catch (error) {
Logger.error(error); Logger.error(error);

View File

@ -5,6 +5,8 @@ import { nanoid } from 'nanoid';
const NOTIFICATION_TTL = 185 * 24 * 60 * 60; // 185 days const NOTIFICATION_TTL = 185 * 24 * 60 * 60; // 185 days
type NotificationType = { type NotificationType = {
id: string;
type: 'SYSTEM' | 'MESSAGE';
content: string; content: string;
time: string; time: string;
}; };
@ -16,25 +18,25 @@ class RedisNotificationStore {
this.redisClient = redisClient; this.redisClient = redisClient;
} }
public async add(userId: string, message: string): Promise<'OK' | 'ERROR'> { public async add(userId: string, content: string, type: NotificationType['type']): Promise<NotificationType> {
try { try {
const key = `notification:${nanoid()}`; const id = nanoid();
const key = `notification:${id}`;
const timestamp = Date.now(); 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.zadd(`user:${userId}`, timestamp, key);
await this.redisClient await this.redisClient.multi().hmset(key, notification).expire(key, NOTIFICATION_TTL).exec();
.multi()
.hmset(key, {
content: message,
time: new Date(timestamp).toISOString(),
})
.expire(key, NOTIFICATION_TTL)
.exec();
return 'OK'; return notification;
} catch (error) { } catch (error) {
Logger.error(error); Logger.error(error);
return 'ERROR'; return Promise.reject(error);
} }
} }