feat: saving notifications

This commit is contained in:
Sergey Yarkov 2022-02-20 23:02:11 +03:00
parent 4056dde970
commit 877e15bcde
5 changed files with 73 additions and 1 deletions

View File

@ -77,11 +77,16 @@ export default class MeService {
});
}
const notifications = await Ws.notificationStore.getNotifications(user.id);
return {
success: true,
status: HttpStatusEnum.OK,
message: 'Fetched authorized user data.',
data: user,
data: {
...user.toJSON(),
notifications,
},
};
}

View File

@ -18,6 +18,7 @@ import AuthMiddleware from 'App/Middleware/Ws/Auth';
*/
import RedisSessionStore from 'App/Store/SessionStore';
import RedisMessageStore from 'App/Store/MessageStore';
import RedisNotificationStore from 'App/Store/NotificationStore';
export interface ServerToClientEvents {
/**
@ -61,6 +62,8 @@ class WsService {
public messageStore: RedisMessageStore;
public notificationStore: RedisNotificationStore;
public booted = false;
public boot() {
@ -81,6 +84,7 @@ class WsService {
*/
this.sessionStore = new RedisSessionStore(Redis.connection('session'));
this.messageStore = new RedisMessageStore(Redis.connection('message'));
this.notificationStore = new RedisNotificationStore(Redis.connection('notification'));
/**
* Clean up sessions before start
@ -125,6 +129,7 @@ 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);
}
});

View File

@ -0,0 +1,53 @@
import { RedisConnectionContract } from '@ioc:Adonis/Addons/Redis';
import Logger from '@ioc:Adonis/Core/Logger';
import { nanoid } from 'nanoid';
const NOTIFICATION_TTL = 185 * 24 * 60 * 60; // 185 days
type NotificationType = {
content: string;
time: string;
};
class RedisNotificationStore {
public redisClient: RedisConnectionContract;
constructor(redisClient: RedisConnectionContract) {
this.redisClient = redisClient;
}
public async add(userId: string, message: string): Promise<'OK' | 'ERROR'> {
try {
const key = `notification:${nanoid()}`;
const timestamp = Date.now();
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();
return 'OK';
} catch (error) {
Logger.error(error);
return 'ERROR';
}
}
public async getNotifications(userId: string) {
const keys = await this.redisClient.zrevrangebyscore(`user:${userId}`, '+inf', '-inf');
const notifications = await Promise.all(keys.map(key => this.get(key)));
return notifications;
}
private async get(key: string): Promise<NotificationType> {
const notification = (await this.redisClient.hgetall(key)) as NotificationType;
return notification;
}
}
export default RedisNotificationStore;

View File

@ -59,6 +59,14 @@ const redisConfig: RedisConfig = {
db: 2,
healthCheck: true,
},
notification: {
host: Env.get('REDIS_HOST'),
port: Env.get('REDIS_PORT'),
password: Env.get('REDIS_PASSWORD', ''),
keyPrefix: '',
db: 3,
healthCheck: true,
},
},
};

View File

@ -10,5 +10,6 @@ declare module '@ioc:Adonis/Addons/Redis' {
local: RedisConnectionConfig;
session: RedisConnectionConfig;
message: RedisConnectionConfig;
notification: RedisConnectionConfig;
}
}