Files
project-inter-server/src/repositories/notifications/RedisNotificationRepository.ts

114 lines
3.7 KiB
TypeScript

import { TupleKey } from '../../types/TupleKey';
import {
Listener,
NotificationEvent,
NotificationLookupArguments,
NotificationRepository,
ScheduledNotification
} from "./NotificationRepository";
import { BaseRedisRepository } from "../BaseRedisRepository";
export class RedisNotificationRepository extends BaseRedisRepository implements NotificationRepository {
private notificationListeners: Listener[] = [];
private readonly NOTIFICATION_KEY_PREFIX = 'notification:';
private getNotificationKey = (shuttleId: string, stopId: string): string => {
const tuple = new TupleKey(shuttleId, stopId);
return `${this.NOTIFICATION_KEY_PREFIX}${tuple.toString()}`;
};
public addOrUpdateNotification = async (notification: ScheduledNotification): Promise<void> => {
const { shuttleId, stopId, deviceId, secondsThreshold } = notification;
const key = this.getNotificationKey(shuttleId, stopId);
await this.redisClient.hSet(key, deviceId, secondsThreshold.toString());
this.notificationListeners.forEach((listener: Listener) => {
const event: NotificationEvent = {
event: 'addOrUpdate',
notification
};
listener(event);
});
};
public deleteNotificationIfExists = async (lookupArguments: NotificationLookupArguments): Promise<void> => {
const { shuttleId, stopId, deviceId } = lookupArguments;
const key = this.getNotificationKey(shuttleId, stopId);
const secondsThreshold = await this.redisClient.hGet(key, deviceId);
if (secondsThreshold) {
await this.redisClient.hDel(key, deviceId);
// Check if hash is empty and delete it if so
const remainingFields = await this.redisClient.hLen(key);
if (remainingFields === 0) {
await this.redisClient.del(key);
}
this.notificationListeners.forEach((listener) => {
const event: NotificationEvent = {
event: 'delete',
notification: {
deviceId,
shuttleId,
stopId,
secondsThreshold: parseInt(secondsThreshold)
}
};
listener(event);
});
}
};
public getAllNotificationsForShuttleAndStopId = async (
shuttleId: string,
stopId: string
): Promise<ScheduledNotification[]> => {
const key = this.getNotificationKey(shuttleId, stopId);
const allNotifications = await this.redisClient.hGetAll(key);
return Object.entries(allNotifications).map(([deviceId, secondsThreshold]) => ({
shuttleId,
stopId,
deviceId,
secondsThreshold: parseInt(secondsThreshold)
}));
};
public getSecondsThresholdForNotificationIfExists = async (
lookupArguments: NotificationLookupArguments
): Promise<number | null> => {
const { shuttleId, stopId, deviceId } = lookupArguments;
const key = this.getNotificationKey(shuttleId, stopId);
const threshold = await this.redisClient.hGet(key, deviceId);
return threshold ? parseInt(threshold) : null;
};
public isNotificationScheduled = async (
lookupArguments: NotificationLookupArguments
): Promise<boolean> => {
const threshold = await this.getSecondsThresholdForNotificationIfExists(lookupArguments);
return threshold !== null;
};
public subscribeToNotificationChanges = (listener: Listener): void => {
const index = this.notificationListeners.findIndex(
(existingListener) => existingListener === listener
);
if (index < 0) {
this.notificationListeners.push(listener);
}
};
public unsubscribeFromNotificationChanges = (listener: Listener): void => {
const index = this.notificationListeners.findIndex(
(existingListener) => existingListener === listener
);
if (index >= 0) {
this.notificationListeners.splice(index, 1);
}
};
}