mirror of
https://github.com/brendan-ch/project-inter-server.git
synced 2026-04-19 08:50:29 +00:00
145 lines
4.5 KiB
TypeScript
145 lines
4.5 KiB
TypeScript
import {
|
|
Listener,
|
|
NotificationEvent,
|
|
NotificationLookupArguments,
|
|
NotificationRepository,
|
|
ScheduledNotification
|
|
} from "./NotificationRepository";
|
|
import { TupleKey } from "../types/TupleKey";
|
|
|
|
type DeviceIdSecondsThresholdAssociation = { [key: string]: number };
|
|
|
|
export class InMemoryNotificationRepository implements NotificationRepository {
|
|
/**
|
|
* An object of device ID arrays to deliver notifications to.
|
|
* The key should be a combination of the shuttle ID and
|
|
* stop ID, which can be generated using `TupleKey`.
|
|
* The value is a dictionary of the device ID to the stored seconds threshold.
|
|
* @private
|
|
*/
|
|
private deviceIdsToDeliverTo: { [key: string]: DeviceIdSecondsThresholdAssociation } = {}
|
|
|
|
private listeners: Listener[] = [];
|
|
|
|
constructor() {
|
|
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);
|
|
}
|
|
|
|
async getAllNotificationsForShuttleAndStopId(shuttleId: string, stopId: string) {
|
|
const tuple = new TupleKey(shuttleId, stopId);
|
|
if (this.deviceIdsToDeliverTo[tuple.toString()] === undefined) {
|
|
return [];
|
|
}
|
|
|
|
return Object.keys(this.deviceIdsToDeliverTo[tuple.toString()])
|
|
.map((deviceId) => {
|
|
return {
|
|
shuttleId,
|
|
stopId,
|
|
deviceId,
|
|
secondsThreshold: this.deviceIdsToDeliverTo[tuple.toString()][deviceId]
|
|
}
|
|
});
|
|
}
|
|
|
|
async getSecondsThresholdForNotificationIfExists({
|
|
shuttleId,
|
|
stopId,
|
|
deviceId
|
|
}: NotificationLookupArguments) {
|
|
const tuple = new TupleKey(shuttleId, stopId);
|
|
if (this.deviceIdsToDeliverTo[tuple.toString()] === undefined) {
|
|
return null;
|
|
}
|
|
return this.deviceIdsToDeliverTo[tuple.toString()][deviceId];
|
|
}
|
|
|
|
async isNotificationScheduled(lookupArguments: NotificationLookupArguments): Promise<boolean> {
|
|
const threshold = await this.getSecondsThresholdForNotificationIfExists(lookupArguments);
|
|
return threshold !== null;
|
|
}
|
|
|
|
async addOrUpdateNotification({
|
|
shuttleId,
|
|
stopId,
|
|
deviceId,
|
|
secondsThreshold
|
|
}: ScheduledNotification) {
|
|
const tuple = new TupleKey(shuttleId, stopId);
|
|
if (this.deviceIdsToDeliverTo[tuple.toString()] === undefined) {
|
|
this.deviceIdsToDeliverTo[tuple.toString()] = {};
|
|
}
|
|
|
|
this.deviceIdsToDeliverTo[tuple.toString()][deviceId] = secondsThreshold;
|
|
this.listeners.forEach((listener: Listener) => {
|
|
const event: NotificationEvent = {
|
|
event: 'addOrUpdate',
|
|
notification: {
|
|
shuttleId,
|
|
stopId,
|
|
deviceId,
|
|
secondsThreshold
|
|
},
|
|
}
|
|
|
|
listener(event);
|
|
})
|
|
}
|
|
|
|
async deleteNotificationIfExists({
|
|
deviceId,
|
|
shuttleId,
|
|
stopId
|
|
}: NotificationLookupArguments) {
|
|
const tupleKey = new TupleKey(shuttleId, stopId);
|
|
if (
|
|
this.deviceIdsToDeliverTo[tupleKey.toString()] === undefined
|
|
|| !(deviceId in this.deviceIdsToDeliverTo[tupleKey.toString()])
|
|
) {
|
|
return;
|
|
}
|
|
|
|
const secondsThreshold = this.deviceIdsToDeliverTo[tupleKey.toString()][deviceId];
|
|
delete this.deviceIdsToDeliverTo[tupleKey.toString()][deviceId];
|
|
|
|
if (Object.keys(this.deviceIdsToDeliverTo[tupleKey.toString()]).length === 0) {
|
|
// no more device IDs remaining for this key combination
|
|
delete this.deviceIdsToDeliverTo[tupleKey.toString()];
|
|
}
|
|
|
|
this.listeners.forEach((listener) => {
|
|
const event: NotificationEvent = {
|
|
event: 'delete',
|
|
notification: {
|
|
deviceId,
|
|
shuttleId,
|
|
stopId,
|
|
secondsThreshold
|
|
}
|
|
}
|
|
|
|
listener(event);
|
|
})
|
|
}
|
|
|
|
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 {
|
|
const index = this.listeners.findIndex((existingListener) => existingListener == listener);
|
|
if (index >= 0) {
|
|
this.listeners.splice(index, 1);
|
|
}
|
|
}
|
|
}
|