diff --git a/src/repositories/BaseRedisRepository.ts b/src/repositories/BaseRedisRepository.ts new file mode 100644 index 0000000..4793d0a --- /dev/null +++ b/src/repositories/BaseRedisRepository.ts @@ -0,0 +1,33 @@ +import { createClient } from 'redis'; + +export abstract class BaseRedisRepository { + protected redisClient; + + constructor( + redisClient = createClient({ + url: process.env.REDIS_URL, + socket: { + tls: (process.env.REDIS_URL?.match(/rediss:/) != null), + rejectUnauthorized: false, + } + }), + ) { + this.redisClient = redisClient; + } + + get isReady() { + return this.redisClient.isReady; + } + + public async connect() { + await this.redisClient.connect(); + } + + public async disconnect() { + await this.redisClient.disconnect(); + } + + public async clearAllData() { + await this.redisClient.flushAll(); + } +} \ No newline at end of file diff --git a/src/repositories/RedisNotificationRepository.ts b/src/repositories/RedisNotificationRepository.ts index cb4a30c..6648642 100644 --- a/src/repositories/RedisNotificationRepository.ts +++ b/src/repositories/RedisNotificationRepository.ts @@ -6,52 +6,18 @@ import { NotificationRepository, ScheduledNotification } from "./NotificationRepository"; -import { createClient } from "redis"; +import { BaseRedisRepository } from "./BaseRedisRepository"; -export class RedisNotificationRepository implements NotificationRepository { +export class RedisNotificationRepository extends BaseRedisRepository implements NotificationRepository { private listeners: Listener[] = []; private readonly NOTIFICATION_KEY_PREFIX = 'notification:'; - constructor( - private redisClient = createClient({ - url: process.env.REDIS_URL, - socket: { - tls: (process.env.REDIS_URL?.match(/rediss:/) != null), - rejectUnauthorized: false, - } - }), - ) { - this.getAllNotificationsForShuttleAndStopId = this.getAllNotificationsForShuttleAndStopId.bind(this); - this.getSecondsThresholdForNotificationIfExists = this.getSecondsThresholdForNotificationIfExists.bind(this); - this.deleteNotificationIfExists = this.deleteNotificationIfExists.bind(this); - this.addOrUpdateNotification = this.addOrUpdateNotification.bind(this); - this.isNotificationScheduled = this.isNotificationScheduled.bind(this); - this.subscribeToNotificationChanges = this.subscribeToNotificationChanges.bind(this); - this.unsubscribeFromNotificationChanges = this.unsubscribeFromNotificationChanges.bind(this); - } - - get isReady() { - return this.redisClient.isReady; - } - - public async connect() { - await this.redisClient.connect(); - } - - public async disconnect() { - await this.redisClient.disconnect(); - } - - public async clearAllData() { - await this.redisClient.flushAll(); - } - - private getNotificationKey(shuttleId: string, stopId: string): string { + private getNotificationKey = (shuttleId: string, stopId: string): string => { const tuple = new TupleKey(shuttleId, stopId); return `${this.NOTIFICATION_KEY_PREFIX}${tuple.toString()}`; - } + }; - public async addOrUpdateNotification(notification: ScheduledNotification): Promise { + public addOrUpdateNotification = async (notification: ScheduledNotification): Promise => { const { shuttleId, stopId, deviceId, secondsThreshold } = notification; const key = this.getNotificationKey(shuttleId, stopId); @@ -64,9 +30,9 @@ export class RedisNotificationRepository implements NotificationRepository { }; listener(event); }); - } + }; - public async deleteNotificationIfExists(lookupArguments: NotificationLookupArguments): Promise { + public deleteNotificationIfExists = async (lookupArguments: NotificationLookupArguments): Promise => { const { shuttleId, stopId, deviceId } = lookupArguments; const key = this.getNotificationKey(shuttleId, stopId); @@ -93,12 +59,12 @@ export class RedisNotificationRepository implements NotificationRepository { listener(event); }); } - } + }; - public async getAllNotificationsForShuttleAndStopId( + public getAllNotificationsForShuttleAndStopId = async ( shuttleId: string, stopId: string - ): Promise { + ): Promise => { const key = this.getNotificationKey(shuttleId, stopId); const allNotifications = await this.redisClient.hGetAll(key); @@ -108,40 +74,40 @@ export class RedisNotificationRepository implements NotificationRepository { deviceId, secondsThreshold: parseInt(secondsThreshold) })); - } + }; - public async getSecondsThresholdForNotificationIfExists( + public getSecondsThresholdForNotificationIfExists = async ( lookupArguments: NotificationLookupArguments - ): Promise { + ): Promise => { 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 async isNotificationScheduled( + public isNotificationScheduled = async ( lookupArguments: NotificationLookupArguments - ): Promise { + ): Promise => { const threshold = await this.getSecondsThresholdForNotificationIfExists(lookupArguments); return threshold !== null; - } + }; - public subscribeToNotificationChanges(listener: Listener): void { + public subscribeToNotificationChanges = (listener: Listener): void => { const index = this.listeners.findIndex( (existingListener) => existingListener === listener ); if (index < 0) { this.listeners.push(listener); } - } + }; - public unsubscribeFromNotificationChanges(listener: Listener): void { + public unsubscribeFromNotificationChanges = (listener: Listener): void => { const index = this.listeners.findIndex( (existingListener) => existingListener === listener ); if (index >= 0) { this.listeners.splice(index, 1); } - } + }; } diff --git a/src/repositories/RedisParkingRepository.ts b/src/repositories/RedisParkingRepository.ts index 99be870..f3beb2f 100644 --- a/src/repositories/RedisParkingRepository.ts +++ b/src/repositories/RedisParkingRepository.ts @@ -1,45 +1,17 @@ -import { createClient } from 'redis'; import { ParkingGetterSetterRepository } from "./ParkingGetterSetterRepository"; import { IParkingStructure, IParkingStructureTimestampRecord } from "../entities/ParkingRepositoryEntities"; import { HistoricalParkingAverageQueryResult, ParkingStructureCountOptions } from "./ParkingGetterRepository"; +import { BaseRedisRepository } from "./BaseRedisRepository"; export type ParkingStructureID = string; // Every 10 minutes export const PARKING_LOGGING_INTERVAL_MS = 600000; -export class RedisParkingRepository implements ParkingGetterSetterRepository { +export class RedisParkingRepository extends BaseRedisRepository implements ParkingGetterSetterRepository { private dataLastAdded: Map = new Map(); private loggingIntervalMs = PARKING_LOGGING_INTERVAL_MS; - constructor( - private redisClient = createClient({ - url: process.env.REDIS_URL, - socket: { - tls: (process.env.REDIS_URL?.match(/rediss:/) != null), - rejectUnauthorized: false, - } - }), - ) { - } - - get isReady() { - return this.redisClient.isReady; - } - - public async connect() { - await this.redisClient.connect(); - } - - public async disconnect() { - await this.redisClient.disconnect(); - } - - public async clearAllData() { - await this.redisClient.flushAll(); - this.dataLastAdded.clear(); - } - addOrUpdateParkingStructure = async (structure: IParkingStructure): Promise => { // Store current structure data await this.redisClient.hSet(`parking:structure:${structure.id}`, {