mirror of
https://github.com/sergeyyarkov/educt-server.git
synced 2026-10-11 10:19:20 +03:00
feat: saving notifications
This commit is contained in:
parent
4056dde970
commit
877e15bcde
@ -77,11 +77,16 @@ export default class MeService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const notifications = await Ws.notificationStore.getNotifications(user.id);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
status: HttpStatusEnum.OK,
|
status: HttpStatusEnum.OK,
|
||||||
message: 'Fetched authorized user data.',
|
message: 'Fetched authorized user data.',
|
||||||
data: user,
|
data: {
|
||||||
|
...user.toJSON(),
|
||||||
|
notifications,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import AuthMiddleware from 'App/Middleware/Ws/Auth';
|
|||||||
*/
|
*/
|
||||||
import RedisSessionStore from 'App/Store/SessionStore';
|
import RedisSessionStore from 'App/Store/SessionStore';
|
||||||
import RedisMessageStore from 'App/Store/MessageStore';
|
import RedisMessageStore from 'App/Store/MessageStore';
|
||||||
|
import RedisNotificationStore from 'App/Store/NotificationStore';
|
||||||
|
|
||||||
export interface ServerToClientEvents {
|
export interface ServerToClientEvents {
|
||||||
/**
|
/**
|
||||||
@ -61,6 +62,8 @@ class WsService {
|
|||||||
|
|
||||||
public messageStore: RedisMessageStore;
|
public messageStore: RedisMessageStore;
|
||||||
|
|
||||||
|
public notificationStore: RedisNotificationStore;
|
||||||
|
|
||||||
public booted = false;
|
public booted = false;
|
||||||
|
|
||||||
public boot() {
|
public boot() {
|
||||||
@ -81,6 +84,7 @@ class WsService {
|
|||||||
*/
|
*/
|
||||||
this.sessionStore = new RedisSessionStore(Redis.connection('session'));
|
this.sessionStore = new RedisSessionStore(Redis.connection('session'));
|
||||||
this.messageStore = new RedisMessageStore(Redis.connection('message'));
|
this.messageStore = new RedisMessageStore(Redis.connection('message'));
|
||||||
|
this.notificationStore = new RedisNotificationStore(Redis.connection('notification'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean up sessions before start
|
* Clean up sessions before start
|
||||||
@ -125,6 +129,7 @@ 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);
|
this.io.to(to).emit('chat:message', message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
53
app/Store/NotificationStore.ts
Normal file
53
app/Store/NotificationStore.ts
Normal 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;
|
||||||
@ -59,6 +59,14 @@ const redisConfig: RedisConfig = {
|
|||||||
db: 2,
|
db: 2,
|
||||||
healthCheck: true,
|
healthCheck: true,
|
||||||
},
|
},
|
||||||
|
notification: {
|
||||||
|
host: Env.get('REDIS_HOST'),
|
||||||
|
port: Env.get('REDIS_PORT'),
|
||||||
|
password: Env.get('REDIS_PASSWORD', ''),
|
||||||
|
keyPrefix: '',
|
||||||
|
db: 3,
|
||||||
|
healthCheck: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -10,5 +10,6 @@ declare module '@ioc:Adonis/Addons/Redis' {
|
|||||||
local: RedisConnectionConfig;
|
local: RedisConnectionConfig;
|
||||||
session: RedisConnectionConfig;
|
session: RedisConnectionConfig;
|
||||||
message: RedisConnectionConfig;
|
message: RedisConnectionConfig;
|
||||||
|
notification: RedisConnectionConfig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user